标签:
看到题,就想到要利用质因子分解进行状压dp,但是质因子太多了,不能直接搞,于是考虑按最大质因子<sqrt(n)和>sqrt(n)分别讨论。对于最大质因子>sqrt(n)的每个数,只有一个质因子>sqrt(n),而<sqrt(n)的质因子是可以状压的。#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<vector>#define ll long long#define inf 1e9#define eps 1e-8using namespace std;int f[270][270],g[2][270][270];bool mark[510];int S[510],P[510],ss[510],t[270],q[510];vector<int> vec[510];int md,m;const int mxs=256,sq=20;inline void add(int &a,int b){a+=b; if (a>=md) a-=md;}void solve(){//printf(":: %d %d %d\n",m,q[1],q[2]);for (int s1=0;s1<mxs;s1++)for (int s2=0;s2<mxs;s2++)g[0][s1][s2]=g[1][s1][s2]=f[s1][s2];for (int i=1;i<=m;i++){int x=q[i];for (int s1=mxs-1;s1>=0;s1--)for (int s2=mxs-1;s2>=0;s2--){if ((x&s2)==0) add(g[0][s1|x][s2],g[0][s1][s2]);if ((x&s1)==0) add(g[1][s1][s2|x],g[1][s1][s2]);}}for (int s1=0;s1<mxs;s1++)for (int s2=0;s2<mxs;s2++){f[s1][s2]=g[0][s1][s2]+g[1][s1][s2]-f[s1][s2];if (f[s1][s2]>=md) f[s1][s2]-=md;if (f[s1][s2]<0) f[s1][s2]+=md;}/*for (int s1=0;s1<4;s1++){for (int s2=0;s2<4;s2++)printf("%d ",f[s1][s2]);printf("\n");}*/}int main(){int n,w=0;scanf("%d%d",&n,&md);for (int i=2;i<=n;i++){if (!mark[i]){ss[++w]=i;S[i]= i>sq?0:(1<<(w-1));P[i]=i;}for (int j=1;ss[j]*i<=n;j++){int p=ss[j],x=i*p;mark[x]=1; S[x]=S[i]|S[p]; P[x]=P[i];if (i%p==0) break;}}for (int i=2;i<=sq;i++) mark[i]=1;t[0]=1;for (int i=2;i<=n;i++)if (P[i]<=sq){vec[1].push_back(S[i]);for (int j=mxs-1;j>=0;j--) add(t[j|S[i]],t[j]);}else vec[P[i]].push_back(S[i]);//for (int i=2;i<=3;i++) printf("%d %d %d\n",mark[i],P[i],S[i]); printf("\n");f[0][0]=1;for (int i=1;i<=n;i++)if (!mark[i]){if (i==1){for (int j=vec[i].size()-1;j>=0;j--){m=1; q[1]=vec[i][j]; solve();}}else{m=0;for (int j=vec[i].size()-1;j>=0;j--) q[++m]=vec[i][j];solve();}}int ans=0;for (int s1=0;s1<mxs;s1++)for (int s2=0;s2<mxs;s2++)add(ans,f[s1][s2]);printf("%d\n",ans);return 0;}
标签:
原文地址:http://blog.csdn.net/heheda_is_an_oier/article/details/51366118