要求A,B选的数两两互质,其实就是把1~n的质因子分配给A,B两个人(可以都不给)
一种朴素的想法是直接状压所有质因子,
注意到实际上在一个数中
的因子至多只会有1个,把他们压到状态里很浪费,而
的因子最多8个,我们状压这8个质因子,
的质因子互相独立,对他们分开dp
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
using namespace std;
const int maxn = 510;
const int mask = 1<<8;
int p[maxn],pri,xp[maxn],v[maxn];
int cov[maxn];
vector<int>V[maxn];
void get_prime()
{
for(int i=2;i<maxn;i++)
{
if(!v[i]) xp[i]=i,p[++pri]=i;
for(int j=1,k=p[j]*i;k<maxn;j++,k=p[j]*i)
{
xp[k]=xp[i]; v[k]=1;
if(i%p[j]==0) break;
}
}
for(int i=2;i<maxn;i++)
{
for(int j=1;j<=8;j++) if(i%p[j]==0) cov[i]|=1<<j-1;
if(xp[i]>p[8]) V[xp[i]].pb(i);
else V[i].pb(i);
}
}
int n,mod;
inline void add(int &a,const int &b){a+=b;if(a>=mod)a-=mod;}
int f[mask][mask],g0[2][mask][mask],g1[2][mask][mask];
int main()
{
get_prime();
scanf("%d%d",&n,&mod);
f[0][0]=1; int S=(1<<8)-1;
for(int i=n;i>=2;i--) if(V[i].size())
{
int now=0;
for(int s1=0;s1<=S;s1++)
{
int oth=S-s1;
for(int s2=oth;;s2=(s2-1)&oth)
{
g0[now][s1][s2]=g1[now][s1][s2]=f[s1][s2];
g0[!now][s1][s2]=g1[!now][s1][s2]=0;
if(!s2) break;
}
}
for(int j=0;j<(int)V[i].size();j++) if(V[i][j]<=n)
{
int x=V[i][j]; now=!now;
for(int s1=0;s1<=S;s1++)
{
int oth=S-s1;
for(int s2=oth;;s2=(s2-1)&oth)
{
int &t1=g0[!now][s1][s2];
add(g0[now][s1][s2],t1);
if(!(cov[x]&s2)) add(g0[now][s1|cov[x]][s2],t1);
t1=0;
int &t2=g1[!now][s1][s2];
add(g1[now][s1][s2],t2);
if(!(cov[x]&s1)) add(g1[now][s1][s2|cov[x]],t2);
t2=0;
if(!s2) break;
}
}
}
for(int s1=0;s1<=S;s1++)
{
int oth=S-s1;
for(int s2=oth;;s2=(s2-1)&oth)
{
f[s1][s2]=(g0[now][s1][s2]+g1[now][s1][s2]-f[s1][s2])%mod;
if(f[s1][s2]<0) f[s1][s2]+=mod;
if(!s2) break;
}
}
}
int ans=0;
for(int s1=0;s1<=S;s1++)
{
int oth=S-s1;
for(int s2=oth;;s2=(s2-1)&oth)
{
add(ans,f[s1][s2]);
if(!s2) break;
}
}
printf("%d\n",ans);
return 0;
}