zoukankan      html  css  js  c++  java
  • BZOJ 4589 Hard Nim

    Description

    Claris和NanoApe在玩石子游戏,他们有n堆石子,规则如下:
    1. Claris和NanoApe两个人轮流拿石子,Claris先拿。
    2. 每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。
    不同的初始局面,决定了最终的获胜者,有些局面下先拿的Claris会赢,其余的局面Claris会负。
    Claris很好奇,如果这n堆石子满足每堆石子的初始数量是不超过m的质数,而且他们都会按照最优策略玩游戏,那么NanoApe能获胜的局面有多少种。
    由于答案可能很大,你只需要给出答案对10^9+7取模的值。

    Input

    输入文件包含多组数据,以EOF为结尾。
    对于每组数据:
    共一行两个正整数n和m。
    每组数据有1<=n<=10^9, 2<=m<=50000。
    不超过80组数据。

    Output

     

    Sample Input

    3 7
    4 13

    Sample Output

    6
    120
    对于该游戏SG[i]=i
    根据SG定理,如果n堆石子的SG异或和为0则后手必胜
    问题变成了,从小于m的素数中可重复选n个,异或和为0,有多少方案
    当n=2时
    可以理解为2个多项式“相乘”
    $C[i]=sum_{j^k=i}A[j]*B[k]$
    这是类似与卷积的形式,其实这可以用FWT$O(mlogm)$实现
    但不可能我们做n次FWT,因为n最大$10^{9}$
    我们发现实际上一次FWT视作一次乘法,就可以看作初始数组$A^{n}$
    A[i]=[i是素数]
    于是可以快速幂
    但实际上没必要在快速幂时用UFWT(逆运算),最后将答案数组UFWT就行了
    这样比每次“相乘”时都FWT和UFWT要好了不少,从$O(mlogmlogn)$变成$O(mlogm+mlogn)$
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 bool vis[50001];
      8 int tot,prime[50001],Mod=1e9+7,inv2,n,m;
      9 int f[200001],a[200001];
     10 void pre()
     11 {int i,j;
     12   for (i=2;i<=50000;i++)
     13     {
     14       if (vis[i]==0)
     15     {
     16       tot++;
     17       prime[tot]=i;
     18     }
     19       for (j=1;j<=tot;j++)
     20     {
     21       if (i*prime[j]>50000) break;
     22       vis[i*prime[j]]=1;
     23       if (i%prime[j]==0) break;
     24     }
     25     }
     26 }
     27 int qpow(int x,int y)
     28 {
     29   int res=1;
     30   while (y)
     31     {
     32       if (y&1) res=1ll*res*x%Mod;
     33       x=1ll*x*x%Mod;
     34       y>>=1;
     35     }
     36   return res;
     37 }
     38 void FWT(int *A,int len)
     39 {int i,j,k;
     40   for (i=1;i<len;i<<=1)
     41     {
     42       for (j=0;j<len;j+=(i<<1))
     43     {
     44       for (k=0;k<i;k++)
     45         {
     46           int x=A[j+k],y=A[j+k+i];
     47           A[j+k]=x+y;
     48           if (A[j+k]>=Mod) A[j+k]-=Mod;
     49           A[j+k+i]=x-y;
     50           if (A[j+k+i]<0) A[j+k+i]+=Mod;
     51         }
     52     }
     53     }
     54 }
     55 void UFWT(int *A,int len)
     56 {int i,j,k;
     57   for (i=1;i<len;i<<=1)
     58     {
     59       for (j=0;j<len;j+=(i<<1))
     60     {
     61       for (k=0;k<i;k++)
     62         {
     63           int x=A[j+k],y=A[j+k+i];
     64           A[j+k]=1ll*(x+y)*inv2%Mod;
     65           A[j+k+i]=1ll*(x-y+Mod)*inv2%Mod;
     66         }
     67     }
     68     }
     69 }
     70 int main()
     71 {int len,i;
     72   inv2=qpow(2,Mod-2);
     73   pre();
     74   while (scanf("%d%d",&n,&m)!=EOF)
     75     {
     76       memset(f,0,sizeof(f));
     77       memset(a,0,sizeof(a));
     78       len=1;
     79       while (len<=m) len*=2;
     80       f[0]=1;
     81       for (i=1;i<=tot;i++)
     82     {
     83       if (prime[i]>m) break;
     84       a[prime[i]]=1;
     85     }
     86       FWT(f,len);FWT(a,len);
     87       while (n)
     88     {
     89       if (n&1)
     90         {
     91           for (i=0;i<len;i++)
     92         f[i]=1ll*f[i]*a[i]%Mod;
     93         }
     94       for (i=0;i<len;i++)
     95         a[i]=1ll*a[i]*a[i]%Mod;
     96       n>>=1;
     97     }
     98       UFWT(f,len);
     99       printf("%d
    ",f[0]);
    100     }
    101 }
  • 相关阅读:
    MongoDB 安装记录
    Vue.JS 对比其他框架
    CSRF攻击原理以及防御
    浏览器何时发送一个Option请求
    Html5 Canvas核心技术(图形,动画,游戏开发)--基础知识
    CSSOM之getboundingclientrect和getclientrects
    CSSOM之getComputedStyle,currentStyle,getPropertyValue,getAttribute
    nodejs 访问mysql
    HTTP请求中的form data和request payload的区别
    html5 drap & drop
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8433008.html
Copyright © 2011-2022 走看看