Learning summary of the new semester 5

Keywords: Algorithm Dynamic Programming

This week, I continued to do questions and found many problems and deficiencies that need to be improved.
P1064 [NOIP2006 improvement group] Jin Ming's budget plan
This is a knapsack problem, but some changes have been added on the basis of the original complete knapsack: each item has at most 2 accessories. Only by adding this item can its accessories be added.
At first, I was a little confused. I directly regarded the attachment as an item, judged it every time I added it to the backpack, and then directly timed out.
After looking at the problem solution, you can actually judge whether it is better to add 0 or 1 or 2 accessories every time you judge whether the main component needs to be added to the backpack, which will not affect the backpack and speed up the speed.

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct piece
{
    int x,y;
} buy[70][3];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int a,b,c;
    for(int j=1; j<=m; j++)
    {
        scanf("%d%d%d",&a,&b,&c);
        if(c==0)
        {
            buy[j][0].x=a;
            buy[j][0].y=b;
        }
        else if(buy[c][1].y==0)
        {
            buy[c][1].x=a;
            buy[c][1].y=b;
        }
        else
        {
            buy[c][2].x=a;
            buy[c][2].y=b;
        }
    }
    int dp[40000]= {0};
    for(int j=1; j<=m; j++)
        for(int i=n; i>=buy[j][0].x; i--)
        {
            dp[i]=max(dp[i],dp[i-buy[j][0].x]+buy[j][0].x*buy[j][0].y);
            if(i-buy[j][0].x-buy[j][1].x>=0)
                dp[i]=max(dp[i],dp[i-buy[j][0].x-buy[j][1].x]+buy[j][0].x*buy[j][0].y+buy[j][1].x*buy[j][1].y);
            if(i-buy[j][0].x-buy[j][2].x>=0)
                dp[i]=max(dp[i],dp[i-buy[j][0].x-buy[j][2].x]+buy[j][0].x*buy[j][0].y+buy[j][2].x*buy[j][2].y);
            if(i-buy[j][0].x-buy[j][1].x-buy[j][2].x>=0)
                dp[i]=max(dp[i],dp[i-buy[j][0].x-buy[j][1].x-buy[j][2].x]+buy[j][0].x*buy[j][0].y+buy[j][1].x*buy[j][1].y+buy[j][2].x*buy[j][2].y);
        }
    printf("%d\n",dp[n]);
}

However, the serial number of the main parts here is not the order of each main part in all main parts, but the order of each main part in all parts. Because of this, I searched for a long time and found out the next day.
P1065 [NOIP2006 improvement group] job scheduling scheme
This is a simulation problem. Because I don't understand this kind of problem, I thought it was a greedy problem at first, and then I thought it was a dp. Finally, I saw the solution of the problem before I knew that there were this type of problems, and then I read the problem carefully before I suddenly became clear.

#include <iostream>
#include <cstdio>
#include <map>
using namespace std;

int main()
{
    int m,n;
    scanf("%d%d",&m,&n);
    int sx[401]={0},jqh[401]={0},sj[401]={0},x;
    map<int,int>c;
    for(int j=1;j<=n*m;j++)
    {
        scanf("%d",&x);
        c[x]++;
        sx[j]=(x-1)*m+c[x];
    }
    for(int j=1;j<=n*m;j++)
        scanf("%d",&jqh[j]);
    for(int j=1;j<=n*m;j++)
        scanf("%d",&sj[j]);
    int jq[21][8001]={0},fin[21]={0};
    for(int j=1;j<=n*m;j++)
    {
        int gj=sx[j]/m;
        int g=jqh[sx[j]];
        int time=sj[sx[j]];
        if(sx[j]%m)
            gj++;
        for(int i=fin[gj]+1;;i++)
        {
            if(jq[g][i]==0)
            {
                int pd=1;
                for(int t=i;t<=i+time-1;t++)
                    if(jq[g][t]!=0)
                        pd=0;
                if(pd==1)
                {
                    for(int t=i;t<=i+time-1;t++)
                        jq[g][t]=1;
                    fin[gj]=i+time-1;
                    break;
                }
            }
        }
    }
    int ans=0;
    for(int j=1;j<=n;j++)
        if(ans<fin[j])
            ans=fin[j];
    printf("%d\n",ans);
}

P1069 [NOIP2009 group] cell division
This is a mathematical problem. Give a base and its power, and then find the number that can be divided by the smallest power operation from the given number. This problem is relatively simple. You only need to calculate the number of prime factors of the base given in each number, and then judge it. However, pay attention to the optimization of time complexity, otherwise it will timeout.
At the beginning, I directly calculated the prime factor of each number, and the result was a direct timeout.

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <climits>
using namespace std;
int pdss(int x)
{
    for(int j=2; j<=sqrt(x); j++)
        if(x%j==0)
            return 0;
    return 1;
}
int main()
{
    int n,m1,m2,s[10001]= {0};
    map<int,int>pd;
    scanf("%d%d%d",&n,&m1,&m2);
    for(int j=1; j<=n; j++)
        scanf("%d",&s[j]);
    s[0]=m1;
    if(m1==1)
    {
        printf("%d\n",0);
        return 0;
    }
    for(int i=2; pdss(m1)!=1&&i<=sqrt(m1); i++)
        while(m1%i==0)
        {
            pd[i]++;
            m1/=i;
        }
    if(m1!=1)
        pd[m1]++;
    for(map<int,int>:: iterator it= pd.begin(); it!=pd.end(); it++)
            it->second*=m2;
    int haveans=0,sc[10001]={0};
    for(int j=1; j<=n; j++)
    {
        int p=1;
        for(map<int,int>:: iterator it= pd.begin(); it!=pd.end(); it++)
            if(s[j]%it->first==0)
            {
                int js=0;
                while(s[j]%it->first==0)
                {
                    s[j]/=it->first;
                    js++;
                }
                int x=it->second/js;
                if(it->second%js!=0)
                    x++;
                sc[j]=max(x,sc[j]);
            }
            else
            {
                p=0;
                break;
            }
        if(p==1)
            haveans=1;
        else
            sc[j]=INT_MAX;
    }
    if(haveans==0)
        printf("%d\n",-1);
    else
    {
        sort(sc+1,sc+1+n);
        printf("%d\n",sc[1]);
    }
    return 0;
}

P1072 [NOIP2009 improvement group] Hankson's interesting questions
I just started to find this problem directly, and then timed out. Later, we know that we can find out the factors of b1 first, and then judge them, which reduces a lot of redundant operations.

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define ll long long
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int n;
    ll a,b,c,d;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
        int ans=0;
        for(ll j=1; j<=sqrt(d); j++)
        {
            if(d%j!=0)
                continue;
            if(j%b==0&&gcd(j,a)==b&&j*c/gcd(j,c)==d)
                ans++;
            if(d/j==j)
                continue;
            if(d/j%b==0&&gcd(d/j,a)==b&&d/j*c/gcd(d/j,c)==d)
                ans++;
        }
        printf("%d\n",ans);
    }
}

By doing these questions, it is found that the ability to find bug s and optimize calculation needs to be improved, and now the problem is too slow and needs to be improved.

Posted by sumitnice@rediffmail.com on Sun, 07 Nov 2021 14:56:50 -0800