zoukankan      html  css  js  c++  java
  • 【BZOJ4589】Hard Nim(FWT+快速幂)

    点此看题面

    大致题意: (nim)游戏,有(n)堆石子,每堆石子个数都是不超过(m)的质数,问后手能赢的方案数。

    (nim)游戏+(FWT)

    显然,根据(nim)游戏的结论,后手能赢意味着石子数异或和为(0)

    考虑我们令(p_i)表示(i)是否为质数,假设当前只有两堆石子,可令:

    [f_i=sum_{j xor k=i}p_j imes p_k ]

    (f_0)就是答案。

    容易发现,(j xor k=i),恰好是(FWT)中异或卷积的条件。

    (n)堆石子,其实就是(n)(p)卷在一起,直接快速幂就行了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define M 50000
    #define P 65536
    #define X 1000000007
    #define I2 500000004
    using namespace std;
    int n,m,p[P],a[P],t[P];
    I void FWT(int *s,CI op)//FWT
    {
    	for(RI i=1,j,k,x,y;i^P;i<<=1) for(j=0;j^P;j+=i<<1) for(k=0;k^i;++k) x=s[j+k],y=s[i+j+k],
    		s[j+k]=(x+y)%X,s[i+j+k]=(x-y+X)%X,op&&(s[j+k]=1LL*s[j+k]*I2%X,s[i+j+k]=1LL*s[i+j+k]*I2%X);
    }
    I void Mul(int *x,int *y) {for(RI i=0;i^P;++i) x[i]=1LL*x[i]*y[i]%X;}//直接乘
    I bool IsP(CI x) {for(RI i=2;i*i<=x;++i) if(!(x%i)) return 0;return 1;}//判断是否为质数
    int main()
    {
    	RI i;for(i=2;i<=M;++i) p[i]=IsP(i);W(scanf("%d%d",&n,&m)==2)//预处理质数表
    	{
    		for(i=0;i^P;++i) a[i]=0,t[i]=1;for(i=1;i<=m;++i) a[i]=p[i];FWT(a,0);//预处理快速幂数组,并用FWT把它变换掉
    		W(n) n&1&&(Mul(t,a),0),Mul(a,a),n>>=1;FWT(t,1),printf("%d
    ",t[0]);//快速幂,然后变回来输出
    	}return 0;
    }
    
  • 相关阅读:
    kubectl命令行工具
    资源编排(YAML)
    vscode自定义vue模板代码
    vscode10个必装的插件
    【转】Android系统开篇
    Android应用资源分析(老罗链接整理)
    APK优化工具zipalign的详细介绍和使用
    Android中APK签名工具之jarsigner和apksigner详解
    Android反编译和二次打包
    python修饰器(装饰器)以及wraps
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4589.html
Copyright © 2011-2022 走看看