zoukankan      html  css  js  c++  java
  • [bzoj1025][SCOI2009]游戏

    题意:可以转化为:把n分成任意个数,这些数的lcm有多少种  n<=1000

    所以把质数筛出来,然后f[i][j]表示前i个质数用j点体力有多少种答案

    枚举i,枚举j,枚举选k个,f[i][j]+=f[i-1][j-s[i]*k] 

    这样就转化为了一道01背包

    复杂度n^1.5*logn

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    bool b[1005];
    ll f[1005][1005],s[1005],n,cnt=0;
    
    int pow(int x,int p)
    {
        if(p==0)return 0;
        int sum=1;
        for(int i=x;p;p>>=1,i=i*i)
            if(p&1) sum=sum*i;
        return sum;
    }
    
    int main()
    {
        for(int i=2;i<=1000;i++)
        {
            if(!b[i]) s[++cnt]=i;
            for(int j=1;j<=cnt&&s[j]*i<=1000;j++)
            {
                b[s[j]*i]=1;if(i%s[j]==0)break;    
            }    
        }
        n=read();f[0][0]=1;int i;
        for(i=1;i<=cnt;i++)
        if(s[i]<=n)
        {
            for(int j=0;j<=n;j++)
            {
                for(int k=0;k<=n;k++)
                {
                    int x=pow(s[i],k);
                    if(x<=j)
                    {
                        f[i][j]+=f[i-1][j-x];    
                    //    cout<<i<<" "<<j<<" "<<k<<" "<<f[i][j]<<endl;
                    }
                    else break;    
                }
            }
        }
        else break;ll ans=0;
        for(int j=1;j<=n;j++)ans+=f[i-1][j];
        cout<<ans+1;
        return 0;
    }
  • 相关阅读:
    最后一周作业
    第十四,十五周作业
    第七周作业
    第六周作业
    第四周作业
    第三周作业
    第二周作业
    二学期第三次作业
    二学期第二次作业
    二学期第一次作业
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1025.html
Copyright © 2011-2022 走看看