题目概述
有
n
堆石子,石子数都是不超过
解题报告
就是求异或和为
0
的方案数。先构造向量
示例程序
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxm=65536,MOD=1e9+7,INV2=MOD+1>>1;
int n,m,p[maxm+5],P[maxm+5],ans[maxm+5];bool pri[maxm+5];
inline void Make(){
pri[0]=pri[1]=true;
for (int i=2;i<=maxm;i++){
if (!pri[i]) p[++p[0]]=i;
for (int j=1,t;j<=p[0]&&(t=i*p[j])<=maxm;j++)
{pri[t]=true;if (!(i%p[j])) break;}
}
}
inline void AMOD(int &x,int tem) {if ((x+=tem)>=MOD) x-=MOD;}
inline void FWT(int *a,int n,int f){
for (int k=1;k<n;k<<=1)
for (int i=0;i<n;i+=k<<1)
for (int j=0;j<k;j++){
int x=a[i+j],y=a[i+j+k];AMOD(a[i+j]=x,y);AMOD(a[i+j+k]=x,MOD-y);
if (f<0) a[i+j]=(LL)a[i+j]*INV2%MOD,a[i+j+k]=(LL)a[i+j+k]*INV2%MOD;
}
}
inline int Pow(int w,int b){
int s=1;
while (b) {if (b&1) s=(LL)s*w%MOD;b>>=1;if (b) w=(LL)w*w%MOD;}
return s;
}
int main(){
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
for (Make();~scanf("%d%d",&n,&m);){
memset(P,0,sizeof(P));for (int i=1;i<=p[0]&&p[i]<=m;i++) P[p[i]]=1;
int x=m;for (m=1;m<=x;m<<=1);FWT(P,m,1);
for (int i=0;i<m;i++) ans[i]=Pow(P[i],n);
FWT(ans,m,-1);printf("%d\n",ans[0]);
}
return 0;
}