<sqrt(500)的质数只有8个
直接状压
剩下的大质数相同的一起dp就行了。
CODE
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 505;
const int S = 256;
const int p[8] = { 2, 3, 5, 7, 11, 13, 17, 19 };
int mp[MAXN], cur, n, f[S][S], g[2][S][S], mod;
vector<int>vec[MAXN];
int main () {
scanf("%d%d", &n, &mod);
for(int i = 2; i <= n; ++i) {
int s = 0, tmp = i;
for(int j = 0; j < 8; ++j) {
if(tmp % p[j] == 0) {
while(tmp % p[j] == 0) tmp /= p[j];
s |= 1<<j;
}
}
vec[tmp==1?++cur:mp[tmp]?mp[tmp]:mp[tmp]=++cur].push_back(s);
}
f[0][0] = 1;
for(int i = 1; i <= cur; ++i) {
for(int j = 0; j < S; ++j)
for(int k = 0; k < S; ++k)
g[0][j][k] = g[1][j][k] = f[j][k];
for(int o = vec[i].size()-1; ~o; --o)
for(int j = S-1; ~j; --j)
for(int k = S-1; ~k; --k)
if((vec[i][o]&k) == 0) {
(g[0][j|vec[i][o]][k] += g[0][j][k]) %= mod;
(g[1][k][j|vec[i][o]] += g[1][k][j]) %= mod;
}
for(int j = 0; j < S; ++j)
for(int k = 0; k < S; ++k)
f[j][k] = (g[0][j][k] + g[1][j][k] - f[j][k]) % mod;
}
int ans = 0;
for(int j = 0; j < S; ++j)
for(int k = 0; k < S; ++k)
(ans += f[j][k]) %= mod;
printf("%d
", (ans + mod) % mod);
}