Daily miscellaneous questions - Review

Posted by maxx99 on Fri, 05 Nov 2021 21:41:04 +0100

multiway merge

62 ugly number

Title Link: Acwing 62 ugly number

146. Sequence

Title Link: acwing 146 sequence

Question meaning: m arrays, n numbers per array. Now in M arrays, each array selects an array into n sequences, with a total width of n m n^m nm selection, find the minimum sum of the first n sequences

Analysis: This is a very classic binary heap problem. I often encounter it. I use the idea of multi-channel merging. Now there are m sequences to be merged. Find the minimum n numbers in front. If there is violence, it will definitely be TLE, so I don't require all of them to be solved by heap

General idea: now m sequences are merged, which is simplified to every two sequences. Find the first n terms of the sum of the two sequences. Observe the following combination to find a property

a 1 , a 2 , a 3 , ... ... , a n a_1,a_2,a_3,......,a_n a1​,a2​,a3​,......,an​
b 1 , b 2 , b 3 , ... ... , b n b_1,b_2,b_3,......,b_n b1​,b2​,b3​,......,bn​
Then we can get n 2 n_2 n2 sum
a 1 + b 1 , a 2 + b 1 , a 3 + b 1 , ... ... , a n + b 1 a_1+b_1,a_2+b_1,a_3+b_1,......,a_n+b_1 a1​+b1​,a2​+b1​,a3​+b1​,......,an​+b1​
a 1 + b 2 , a 2 + b 2 , a 3 + b 2 , ... ... , a n + b 2 a_1+b_2,a_2+b_2,a_3+b_2,......,a_n+b_2 a1​+b2​,a2​+b2​,a3​+b2​,......,an​+b2​
............................................................
a 1 + b n , a 2 + b n , a 3 + b n , ... ... , a n + b n a_1+b_n,a_2+b_n,a_3+b_n,......,a_n+b_n a1​+bn​,a2​+bn​,a3​+bn​,......,an​+bn​

When a is ordered, the minimum value of each row (Group) is the first
So we want to find the sum of the minimum, then find the minimum in these n

Suppose found a 1 + b 2 a_1+b_2 a1 + b2 , then the array becomes
a 1 + b 1 , a 2 + b 1 , a 3 + b 1 , ... ... , a n + b 1 a_1+b_1,a_2+b_1,a_3+b_1,......,a_n+b_1 a1​+b1​,a2​+b1​,a3​+b1​,......,an​+b1​
a 2 + b 2 , a 3 + b 2 , ... ... , a n + b 2 a_2+b_2,a_3+b_2,......,a_n+b_2 a2​+b2​,a3​+b2​,......,an​+b2​
............................................................
a 1 + b n , a 2 + b n , a 3 + b n , ... ... , a n + b n a_1+b_n,a_2+b_n,a_3+b_n,......,a_n+b_n a1​+bn​,a2​+bn​,a3​+bn​,......,an​+bn​

The minimum value of the second group becomes a 2 + b 2 a_2+b_2 a2 + b2 , then compare with other sums until the nth end is found, and repeat the process

m arrays are merged m-1 times to find the minimum sequence sum of the first n items

#include<iostream>
#include <vector>
#include <cmath>
#include<cstring>
#include<algorithm>
#include <queue>
#include<cstdio>
#include<cstring>
using namespace std;
typedef pair<int, int> PII;

const int N = 2400;
int t,n,m;
int a[N],b[N],k[N];

//Merge the two arrays to find the first n minimum values
void merg()
{
    //multiway merge 
    //Each time the small top heap finds the smallest addition, and then the one behind + + is added to the heap
    priority_queue<PII,vector<PII>,greater<PII> > heap;
    for(int i=0;i<n;i++)heap.push({a[0]+b[i],0});
    int c=0;
    while(c<n)
    {
        int f=heap.top().first;
        int s=heap.top().second;
        heap.pop();
        k[c++]=f;
        heap.push({f-a[s]+a[s+1],s+1});
    }
    for(int i=0;i<n;i++)
        a[i]=k[i];
    
}

int main()
{
    cin>>t;
    while(t--)
    {
        
        cin>>m>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        //Sort first 
        //Ensure the order in the first group of each sequence at the beginning 
        
        sort(a,a+n);
        m--;
        while (m -- )
        {
            for(int i=0;i<n;i++)
            cin>>b[i];
            
            merg();
            
        }
        for(int i=0;i<n;i++)
            cout<<a[i]<<' ';
        cout<<endl;
        
    }
    
    return 0;
}

1262 fish pond fishing

Title Link: Acwing 1262 fish pond fishing

Meaning: for n fish ponds, for each minute of fishing in the fish pond, the reduction x of fishing number in the next minute. Moving to adjacent fish ponds requires l grouping. Ask the maximum fishing value at T time

Analysis: for hidden multi-channel merging, you can't go back every time you go to a fish pond. In this way, it's better to fish this minute directly after passing through the fish pond. When the passing time is fixed, that is, when the time on the road is fixed, there is only fishing time left, and the maximum value is taken
The final idea is to enumerate the time on the road, fishing time, greedy for the most fish in the fish pond, and take max

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;

const int N = 110;
int n,T;
int a[N],t[N],l[N];

long long solve(int index,int time)
{
    priority_queue<int,vector<int>> heap;
    for(int i=0;i<=index;i++)
    {
        int x=a[i];
        while(x>0)
        {
            heap.push(x);
            x-=t[i];
        }
    }
    long long sum=0;
    while(time>0&&heap.size())
    {
        sum+=heap.top();
        heap.pop();
        time--;
        
    }//cout<<sum<<endl;
    return sum;
}

int main()
{
    
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=0;i<n;i++)cin>>t[i];
    for(int i=1;i<=n-1;i++)
    {
        cin>>l[i];
        l[i]+=l[i-1];
    }
    cin>>T;
    
    long long sum=0;
    for(int i=0;i<=n-1;i++)
        sum=max(sum,solve(i,T-l[i]));
    cout<<sum<<endl;
    return 0;
}

Matrix fast power

HDU1575Tr A

Title Link: HDU1575

Matrix fast power board subproblem

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>

using namespace std;
const int mod=9973;
struct Eur{
    int a[10][10];
}res;
int T,n,k;

Eur quick(Eur x,Eur y)
{
    Eur t;
    memset(t.a,0,sizeof(t.a));
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        t.a[i][j]=0;

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int p=0;p<n;p++)
            t.a[i][j]=(t.a[i][j]+x.a[i][p]*y.a[p][j])%mod;

    return t;
}

void quickE(int k)
{
    Eur ans;
    memset(ans.a,0,sizeof(ans.a));
    for(int i=0;i<n;i++)ans.a[i][i]=1;

    while(k)
    {
        if(k&1)ans=quick(ans,res);
        res=quick(res,res);
        k>>=1;
    }
    int sum=0;
    for(int i=0;i<n;i++)sum=(sum+ans.a[i][i])%mod;
    printf("%d\n",sum);

}

int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n>>k;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {int x;cin>>x;res.a[i][j]=x%mod;}
        quickE(k);
    }

    return 0;
}

POJ - 3233 Matrix Power Series

Title Link: POJ - 3233

Violence: Circular necessity TLE
Optimization: matrix fast power
matrix
E E S1 = Sk
o A A2 = A^k+1

matrix multiplication
Matrix multiplication of an nn
Multiplication of a 2nn matrix
Multiply a 2n*2n matrix
Three I wrote three broad to write simple points
At first, the multiplication matrix was written wrong, wa and n hair

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>

using namespace std;
typedef long long ll;

struct mat{
    ll a[120][121];
}res;

ll n,mod,k;

mat quick(mat x,mat y)
{
    mat t;
    memset(t.a,0,sizeof(t.a));

    for(int i=0;i<2*n;i++)
        for(int j=0;j<2*n;j++)
            for(int p=0;p<2*n;p++)
                t.a[i][j]=(t.a[i][j]+x.a[i][p]*y.a[p][j]%mod+mod)%mod;
    return t;
}

mat quickp(mat x,mat y)
{
    mat t;
    memset(t.a,0,sizeof(t.a));

    for(int i=0;i<2*n;i++)
        for(int j=0;j<n;j++)
            for(int p=0;p<2*n;p++)
                t.a[i][j]=(t.a[i][j]+x.a[i][p]*y.a[p][j]%mod)%mod;
    return t;
}

mat quick2(mat x,mat y)
{
    mat t;
    memset(t.a,0,sizeof(t.a));

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int p=0;p<n;p++)
                t.a[i][j]=(t.a[i][j]+x.a[i][p]*y.a[p][j]%mod+mod)%mod;
    return t;
}

mat quickm(mat x,ll k)
{
    mat ans;
    memset(ans.a,0,sizeof(ans.a));
    for(int i=0;i<2*n;i++)ans.a[i][i]=1;

    while(k)
    {
        if(k&1)ans=quick(ans,x);
        x=quick(x,x);
        k>>=1;
    }
    return ans;
}

int main()
{
    cin>>n>>k>>mod;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {ll x;cin>>x;res.a[i][j]=x%mod;}

    mat p,w;

    w=quick2(res,res);

    memset(p.a,0,sizeof(p.a));
    for(int i=0;i<n;i++)
        p.a[i][i]=1;
    for(int i=0;i<n;i++)
        p.a[i][i+n]=1;


    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        p.a[i+n][j+n]=res.a[i][j];

    p=quickm(p,k-1);

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        res.a[i+n][j]=w.a[i][j];

    mat r=quickp(p,res);

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            if(j==0)printf("%lld",r.a[i][j]);
            else printf(" %lld",r.a[i][j]);
        printf("\n");
    }
    return 0;
}

Prime factor decomposition

HDU 6287 oral arithmetic training

Title Link: HDU 6287 oral arithmetic training

Analysis: this question looks at the data range, directly pass es violence, and then the product of each interval% d==0
It seems that the line segment tree will also tml
Final ac practice: decompose the quality factor
Use vector to record the index (subscript) of each prime number
Then decompose d with prime every time to see if there are so many prime numbers in l-r

#include<iostream>
#include<math.h>
#include<cstdio>
#include<algorithm>

using namespace std;

const int N = 1e5+10;
int t,n,m;
int a[N];
vector<int>ve[N];

//Finding prime number by linear sieve method
int primes[N], cnt;		// Primes [] stores all primes
bool st[N];			// st[x] is storage x screened out

void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

//Decompose each number and add index to the list of prime factors
void fen(int val,int index)
{
    for(int i=0;st[val];i++)
    {
        while(val%primes[i]==0)
        {
            ve[primes[i]].push_back(index);
            val/=primes[i];
        }

    }
    if(val>1)ve[val].push_back(index);
}

int main()
{
    scanf("%d",&t);

    get_primes(N);

    while(t--)
    {
        scanf("%d%d",&n,&m);
        //Reset every initialization
        for(int i=0;i<cnt;i++)
        ve[primes[i]].clear();

        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            fen(a[i],i);
        }

        while(m--)
        {
            int l,r,d;
            scanf("%d%d%d",&l,&r,&d);
            bool flag=true;
            for(int i=0;st[d];i++)
            {
                int num=0;
                while(d%primes[i]==0)
                {
                    num++;
                    d/=primes[i];
                }

                if(num==0)continue;
                //Find the number of prime in the range of l and r and optimize it with lower bound
                int ll=lower_bound(ve[primes[i]].begin(),ve[primes[i]].end(),l)-ve[primes[i]].begin();
                int rr=upper_bound(ve[primes[i]].begin(),ve[primes[i]].end(),r)-ve[primes[i]].begin();
                //cout<<num<< ' '<<ll<<" "<<rr<<endl;
                if(rr-ll<num)
                {
                    flag=false;
                    break;
                }

            }
            //The final d is prime
            if(d!=1&&flag)
            {
                int ll=lower_bound(ve[d].begin(),ve[d].end(),l)-ve[d].begin();
                int rr=upper_bound(ve[d].begin(),ve[d].end(),r)-ve[d].begin();
                if(rr-ll<1)
                {
                    flag=false;
                }
            }
            if(flag)puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

Topics: ICPC