zoukankan      html  css  js  c++  java
  • P1857 质数取石子 (DP,递推)

    题目描述

    桌上有若干个石子,每次可以取质数个。谁先取不了,谁就输。问最少几步能赢?(一个人取一次算一步)

    输入输出格式

    输入格式:

    第一行N,表示有N组数据

    接下来N行为石子数

    输出格式:

    每组数据一个数,若必胜,则输出最少步数,否则输出-1

    输入输出样例

    输入样例#1: 
    3
    8
    9
    16
    输出样例#1: 
    1
    -1
    3

    说明

    石子数≤20000,N≤10

    Solution

    NIm 游戏的质数版 思路基本和原版一致 即每一个必胜状态都由上一次必败的状态转过来.然后需要先一个筛法筛出20000以内的质数. 然后照Nim 游戏的动规方程 即可.不过这里的状态要多加一维用于加上场数这个信息的保存. 这里用的是

    f[i][0] 代表场数

    f[i][1] 代表 

      1 -->  必胜

      -1 --> 必败

    细节就是质数枚举的时候要倒着从大的开始 否则会有鬼.

    代码 :

    #include<bits/stdc++.h>
    using namespace std;
    int n,f[20010][2]={0},a[20];
    int p[3000],maxn=-1,sum;
    
    int v[20008];
    void pre()
    {
        for(int i=2;i<=20008;i++)
        {
            if(v[i]==0)
            {
            p[++sum]=i;
            for(int j=1;j*i<=20001;j++)
                v[i*j]++;
            }
        }
    }
    
     void solve()
    {
        f[0][1]=-1;f[0][0]=0;
        f[1][1]=-1;f[1][0]=0;
        f[2][1]=1;f[2][0]=1;
        f[3][1]=1;f[3][0]=1;//初始化几个点
        for(int i=4;i<=maxn;++i)
        for(int j=sum;j>=1;--j)
        if(p[j]<=i)
        { 
            if(f[i-p[j]][1]==-1)            //前驱为必败
            if(f[i][1]==0||f[i][1]==-1)//尚未判定状态
            {
                f[i][1]=1;                        
                f[i][0]=f[i-p[j]][0]+1;
            }
            else
            f[i][0]=min(f[i][0],f[i-p[j]][0]+1);//选取场数最小值
            if(f[i-p[j]][1]==1)//前驱为必胜
            if(f[i][1]==0)
            {
                f[i][1]=-1;
                f[i][0]=f[i-p[j]][0]+1;
            }
            else if(f[i][1]==-1)
            f[i][0]=max(f[i][0],f[i-p[j]][0]+1); //败了久选最大值.
        }
        return;
    }
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            maxn=max(a[i],maxn);
        }
       pre();
        solve();
        for(int i=1;i<=n;i++)
        if(f[a[i]][1]==-1)
        printf("-1
    ");
        else printf("%d
    ",f[a[i]][0]);
        return 0;
    }
  • 相关阅读:
    HTTP状态码
    TCP慢启动、拥塞避免、快速重传、快速恢复(转)
    优化js设计,防止浏览器假死(转)
    Firebug详解(转)
    WUST Online Judge
    WUST Online Judge
    WUST Online Judge
    WUST Online Judge
    WUST Online Judge
    WUST Online Judge
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/8646637.html
Copyright © 2011-2022 走看看