• FWT [BZOJ 4589:Hard Nim]


    4589: Hard Nim

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 275  Solved: 152
    [Submit][Status][Discuss]

    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
     
     
    其实这题和上午XJOI里的T3差不多。
    具体做法请看别人博客http://blog.csdn.net/jr_mz/article/details/51606673
    然而 问题来了。第一次我TLE了,交了Mz的代码 发现他只要6s。
    然后仔细对比。。。看了好久祝天然的代码。 得出结论【啊首先 只要不开LL就不会TLE。但是时间的瓶颈不在这。】:
      FWT的数组n(是2的幂、当然)只要大于(注意是严格大于。否则就WA了)其中的任意一个元素就可以。
     
    恩。再贴一下各种FWT的公式
    xor:

    and:

    or:

    其实公式蛮好推的。。而且也不唯一  比如说 xor  还可以是 A=(A0-A1,A0+A1) 逆A就再反着算一下就可以

    还有 FWT只是沿用 FFT和NTT的思想。

    【FFT的思想,构造一种可逆的特殊变换trans,使得(trans(a*b))[i]=(trans(a))[i]*(trans(b))[i]。】

    但是从界门纲目科属种来看 还是不像FFT与NTT 如此相似。

    FWT不需要rev数组 ,举例N=8,下标为0~7。变换的时候,先对01,23,45,67做,再对02,13,46,57做,最后对04,15,26,37做。逆变换把顺序反过来就好了。

    而且,这种特殊多项式乘法 满足结合律  ,trans后可以快速幂。

    贴本题代码:

     1 #include <bits/stdc++.h>
     2 #define LL long long
     3 const int mo=1000000007;
     4 using namespace std;
     5 int x,y,n,m,a[60005],T,t,f[140000];
     6 LL po(LL x,LL y){
     7     LL z=1;
     8     for (;y;y>>=1,x=x*x%mo)
     9     if (y&1) z=z*x%mo;
    10     return z;
    11 }
    12 void fwt(int *a,int n,int d){
    13     for (m=2;m<=n;m<<=1)
    14     for (int i=0,k=m>>1;i<n;i+=m)
    15     for (int j=i;j<i+k;++j){
    16         int u=a[j],v=a[j+k];
    17         a[j]=(u+v)%mo,a[j+k]=(u-v)%mo;
    18     }
    19     if (d<0){
    20         LL x=po(n,mo-2);
    21         for (int i=0;i<n;++i) a[i]=x*a[i]%mo;
    22     }
    23 }//注意a[i]<0
    24 int main(){
    25     for (int i=2;i<=60000;++i){
    26         if (!a[i]) a[++T]=i;
    27         for (int j=1;j<=T;++j){
    28             int x=a[j]*i; if (x>60000) break;
    29             a[x]=1; if (!(i%a[j])) break;
    30         }
    31     }
    32     while (scanf("%d%d",&x,&y)==2){
    33         for (t=1;a[t]<=y;++t) f[a[t]]=1; --t;
    34         for (n=1;n<=a[t];n<<=1);
    35         fwt(f,n,1);
    36         for (int i=0;i<n;++i) f[i]=po(f[i],x);
    37         fwt(f,n,-1);
    38         printf("%d
    ",(f[0]+mo)%mo);
    39         for (int i=0;i<n;++i) f[i]=0;
    40     }
    41     return 0;
    42 }
    化け物
  • 相关阅读:
    Javascript跨域后台设置拦截
    Hello ReactJS
    Redis 常用监控信息命令总结
    MySQL架构与业务总结图
    MySQL垂直拆分和水平拆分的优缺点和共同点总结
    MySQL实用工具汇总
    MySQL查看数据库表容量大小
    MySQL到底能支持多大的数据量?
    微信小程序wxss的background本地图片问题
    微信小程序中显示与隐藏(hidden)
  • 原文地址:https://www.cnblogs.com/cyz666/p/6556792.html
Copyright © 2020-2023  润新知