• HDU


    problem:给定N,K。表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数。N,K<500;

    solution:显然可以状压DP做,但是500以内的素数还是蛮多的,无法高效得DP。   但是我们注意到,大于sqer(N)的素数,同一类最多用一个,这不就是分组背包吗。

    所以我们只有小于sqrt(N)的素数用常规的DP,否则用分组背包。 dp[i][j]表示选择了i个数,其中小于sqrt(N)的素数状态为j。 j<(1<<8);

    分组背包:我们把个数放在第一维,就保证了同一类的物品不相互影响,做到了分组。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int Mod=1e9+7;
    const int maxn=510;
    int dp[maxn][256],a[maxn],x[maxn];
    int p[]={2,3,5,7,11,13,17,19};
    vector<int>G[maxn];
    void init(int N)
    {
        rep(i,1,N) G[i].clear();
        rep(i,1,N){
            int t=i,tmp=0;
            rep(j,0,7){
                if(t%(p[j]*p[j])==0) {
                    t=-1;
                    break;
                }
                if(t%p[j]==0) {
                    t/=p[j];
                    tmp|=(1<<j);
                }
            }
            if(t!=-1) {
                G[t].push_back(i);
                x[i]=tmp;
            }
        }
    }
    int main()
    {
        int N,T,K,ans;
        scanf("%d",&T);
        while(T--){
            memset(dp,0,sizeof(dp));
            dp[0][0]=1; ans=0;
            scanf("%d%d",&N,&K);
            init(N);
            rep(j,0,G[1].size()-1) //1单独考虑
              for(int v=K-1;v>=0;v--){
                 int t=G[1][j];
                 rep(k,0,255){
                    if((x[t]&k)==0){
                        (dp[v+1][k|x[t]]+=dp[v][k])%=Mod;
                    }
                }
            }
            rep(i,2,N){
                if(G[i].size()==0) continue;
                for(int v=K-1;v>=0;v--) //放在第一维保证了分组
                 rep(j,0,G[i].size()-1){
                    int t=G[i][j];
                    rep(k,0,255){
                        if((x[t]&k)==0){
                            (dp[v+1][k|x[t]]+=dp[v][k])%=Mod;
                        }
                    }
                }
            }
            rep(j,1,K)
             rep(i,0,255) (ans+=dp[j][i])%=Mod;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    算法---十大经典排序算法
    算法---待整理
    iOS面试题整理---[难度]***
    spring mvc(注解)上传文件的简单例子
    面试感悟:3年工作经验程序员应有的技能
    一个 IT 青年北漂四年的感悟
    成为更优秀程序员的关键:更多的阅读
    数组参数 有params 区别
    对C# 集合类的总结
    c#前缀
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10799850.html
Copyright © 2020-2023  润新知