原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=4197
这和今年THUSC的一题有点像,都是将根号以内的质数作状态。
首先每个质数都只能在一边出现一次,考虑状压,把包含质数的二进制压成状态,两边质数不能有交集,每次一个数放进来,枚举放左边,放右边和不放。但
n
以内质数有95个,考虑一个数大于
已经加了枚举子集的小小优化,但跑下来时间还是没达到bzoj平均水平,不过是1A,开心。(再也不会忘记+P再取模啦)
#include<bits/stdc++.h>
typedef long long ll;
const int N = 505;
const int all = 1 << 8;
const int p[8] = {2,3,5,7,11,13,17,19};
struct rec{
int s,b;
}a[N];
int n,P;
ll f[all][all],g[2][all][all],ans;
bool cmp(const rec &a, const rec &b){
return a.b > b.b;
}
int main(){
scanf("%d%d",&n,&P);
for (int i=1; i<n; i++){
int temp = i + 1;
for (int j=0; j<8; j++){
a[i].s = a[i].s * 2 + (temp % p[j] == 0);
while (temp % p[j] == 0) temp /= p[j];
}
a[i].b = temp;
}
n--;
std::sort(a+1,a+n+1,cmp);
g[0][0][0] = 1;
g[1][0][0] = 1;
f[0][0] = 1;
for (int i=1; i<=n; i++){
if (i == 1 || a[i].b != a[i-1].b || a[i].b == 1)
for (int S=0; S<all; S++)
for (int _S=0; _S<all; _S++)
f[S][_S] = (g[0][S][_S] + g[1][S][_S] - f[S][_S]) % P,
g[0][S][_S] = g[1][S][_S] = f[S][_S];
int _C = (all - 1) ^ a[i].s;
for (int _S = _C; _S>=0; _S = (_S - 1) & _C){
int C = (all - 1) ^ _S;
for (int S = C; S>=0; S = (S - 1) & C){
g[0][S | a[i].s][_S] = (g[0][S | a[i].s][_S] + g[0][S][_S]) % P;
g[1][_S][S | a[i].s] = (g[1][_S][S | a[i].s] + g[1][_S][S]) % P;
if (!S) break;
}
if (!_S) break;
}
}
for (int S=0; S<all; S++)
for (int _S=0; _S<all; _S++)
ans += g[0][S][_S] + g[1][S][_S] - f[S][_S];
printf("%lld\n",(ans % P + P) % P);
return 0;
}