zoukankan      html  css  js  c++  java
  • 【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
    ",k,dp[n&1][(1<<bit)-1]+(d!=1)+f[n]);
        }
        return 0;
    }
    

    2018.12.13

  • 相关阅读:
    两个不同于LR和jmeter的性能测试工具
    一个基于集成jenkins的测试平台
    sparkR原理
    Python 出现需要使用fPIC重新编译的问题
    eclipse中使用jython
    R中逻辑运算
    R语言的一些笔记
    Distributed R
    R语言和大数据
    Mysql command line
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10113589.html
Copyright © 2011-2022 走看看