BZOJ4589 Hard Nim FWT 快速幂 博弈
2024-10-11 10:14:14
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4589.html
题目传送门 - BZOJ4589
题意
有 $n$ 堆石子,每一堆石子的取值为 $2$ ~ $m$ 之间的素数。
问在所有不同的取值中,先手必败的方案总数。
答案对 $10^9+7$ 取模。
$n\leq 10^9,m\leq 50000$
题解
第一次写 FWT 。
感觉 FWT 比 FFT 简单多了。
下面进入正题。
首先,我们再回顾一下 Nim游戏 中先手必败的情况:所有数的异或和为 $0$ 。具体证明自行百度,这里不加赘述。
我们构造一个多项式 $A$ ,如果 $i$ 为素数,那么 $A(i)=1$ ,否则 $A(i)=0$ 。
定义卷积如下形式:
$$C(k)=\sum_{i\ XOR\ j=k} A(i)B(j)$$
于是我们看到,如果 $n=2$ ,那么答案为 $A^2(0)$ 。
类似地,原题答案为 $A^n(0)$ 。
注意一下上面的那个卷积式可以用 FWT 来做。
我们先 FWT 一下,类似于多项式点值相乘,异或卷积的“点值”也可以自己相乘,于是每一个值都直接取其 $n$ 次方,然后再 IFWT 一下就可以得到目标多项式了。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1<<16,mod=1e9+7,inv2=(mod+1)/2;
int Pow(int x,int y){
if (!y)
return 1;
int xx=Pow(x,y/2);
xx=1LL*xx*xx%mod;
if (y&1)
xx=1LL*xx*x%mod;
return xx;
}
bool check(int x){
for (int i=2;i*i<=x;i++)
if (x%i==0)
return 0;
return x>1;
}
int n,m,k,A[N];
void FWT(int a[],int n,int flag){
for (int d=1;d<n;d<<=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod;
a[i+j+d]=(x-y+mod)%mod;
if (flag<0){
a[i+j]=1LL*a[i+j]*inv2%mod;
a[i+j+d]=1LL*a[i+j+d]*inv2%mod;
}
}
}
int main(){
while (~scanf("%d%d",&k,&m)){
for (n=1;n<=m;n<<=1);
for (int i=0;i<n;i++)
A[i]=(check(i)&&i<=m)?1:0;
FWT(A,n,1);
for (int i=0;i<n;i++)
A[i]=Pow(A[i],k);
FWT(A,n,-1);
printf("%d\n",A[0]);
}
return 0;
}
最新文章
- Javascript实现HashTable类
- 浅谈WebSocket
- 用户控件UserControl图片资源定位(一)---Xaml引用图片
- thinkphp用phpexcel读取excel,并修改列中的值,再导出excel,带往excel里写入图片
- Django 1.6 最佳实践: 如何设置django项目的设置(settings.py)和部署文件(requirements.txt)
- 如何禁用 radio ,设置为只读,不能选定
- careercup-树与图 4.3
- IOSi科研OS7 具体的使用说明的适应
- Android下拉刷新上拉载入控件,对全部View通用!
- javascript 判断质数
- Android屏幕相关的概念
- 学习笔记GAN002:DCGAN
- 仿迅雷播放器教程 -- 十年经验大牛对MFC的认识 (7)
- [Bayes] Hist &; line: Reject Sampling and Importance Sampling
- vue.js - 1
- hdu2609 最小表示法
- Linux squid 缓存服务器
- jQuery 中 attr() 和 prop() 方法的区别<;转>;
- Django之验证码的生成和使用
- chrome调试微信