【51Nod1386】双马尾机器人Description 解题报告

【51Nod1386】双马尾机器人Description

​ 给定\(n\)\(k\),我们要在\(1,2,3,...,n\)中选择若干的数,每一种选择的方案被称为选数方案。
​ 我们定义一种选数方案是合法的,当且仅当\(k\)没有被选,且任意两个选的数互质。
​ 我们定义一种选数方案是极大的,当且仅当它是合法的,且不能再从剩下的数中选择任意一个,或者选的是\(k\)
​ 求极大的选数方案的最小的选的个数。

Input

第一行输入一个\(T\),表示数据组数。
接下来\(T\)行,每行输入整数\(n\)\(k\),表示球的个数和不能选的编号。

Output

对于每组\(case\),输出一行:"Case #X: Y", \(X\)表示数据编号,\(Y\)表示最少拿走的球的数量。

HINT

\(1≤T≤50\)
\(1≤n≤1000\)\(1≤k≤n\)\(k\)不是质数


这个思维方式还是要积累一下的。

注意到\(>\sqrt N\)的质数在一个数中不可能同时出现两个,所以每一个大于的质数都可以直接作为贡献(注意\(k\)不是质数)

然后我们发现\(<\sqrt N\)的质数只有\(11\)个,我们可以状压这个集合

\(dp_{i,j}\)代表前\(i\)个数选出了质因子集合\(j\)的最小选择数量

有转移\(dp_{i,j|sta_i}=\min(dp_{i-1,j}+1-[v_i<\sqrt N],dp_{i,j|sta_i})(if \ j\&sta_i==0)\)

其中\(sta_i\)代表\(i\)这个数的质因数集合,\(v_i\)表示这个数的最大质因数(毕竟大于\(\sqrt N\)的数在外面算过了)

最后的结果是\(dp_{n,all}\),因为我们一定是可以选出这个全集的,然后题目要求我们选这个全集。


Code:

#include <cstdio>
#include <cstring>
const int N=1000;
const int t[12]={0,2,3,5,7,11,13,17,19,23,29,31};
int pri[N+10],ispri[N+10],v[N+10],cnt;
int n,k,T,dp[2][1<<11],sta[N+10],f[N+10];
int min(int x,int y){return x<y?x:y;}
void init()
{
    for(int i=2;i<=N;i++)
    {
        for(int j=1;j<=11;j++)
            if(i%t[j]==0)
                sta[i]|=1<<j-1;
        f[i]=f[i-1];
        if(!ispri[i])
        {
            v[i]=i;
            f[i]+=v[i]>3
            pri[++cnt]=i;
        }
        for(int j=1;j<=cnt&&i*pri[j]<=N;j++)
        {
            ispri[i*pri[j]]=1;
            v[i*pri[j]]=v[i];
            if(i%pri[j]==0) break;
        }
    }
}
int main()
{
    scanf("%d",&T);
    init();
    for(int n,d,k=1;k<=T;k++)
    {
        scanf("%d%d",&n,&d);
        int bit=1;
        while(bit<=11&&t[bit]<=n) ++bit;--bit;
        memset(dp,0x3f,sizeof(dp));
        dp[1][0]=0;
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<1<<bit;j++) dp[i&1][j]=dp[i-1&1][j];
            if(i==d) continue;
            for(int j=0;j<1<<bit;j++)
                if(!(sta[i]&j))
                    dp[i&1][j|sta[i]]=min(dp[i-1&1][j]+1-(v[i]>31),dp[i&1][j|sta[i]]);
        }
        printf("Case #%d: %d\n",k,dp[n&1][(1<<bit)-1]+(d!=1)+f[n]);
    }
    return 0;
}

2018.12.13

猜你喜欢

转载自www.cnblogs.com/ppprseter/p/10113589.html