果然我还是太菜了......
T1:
先分解成标准形式,然后每个质因数必须有最高次,然后状压DP?
发现并不可做......
然后写了10分的大力背包走了......
正解是容斥。
然而他的公式挂了......
大概意思就是枚举我们有几个没有到最高次,然后用高维前缀和(积)进行DP。
关于高维前缀和可以看我以前的博客......
为什么考场没想起来......
考场10分代码:
1 #include<cstdio> 2 #include<cstring> 3 //#include<iostream> 4 //#define debug cout 5 //using namespace std; 6 typedef long long int lli; 7 const int maxn=5e2+1e1,maxk=22; 8 const int mod=232792561; 9 10 lli f[2][maxn][maxk]; 11 int n,k; 12 13 inline int gcd(int x,int y) { 14 register int t; 15 while( t = x % y ) 16 x = y , y = t; 17 return y; 18 } 19 inline int lcm(int x,int y) { 20 if( ! ( x && y ) ) return x | y; 21 return x / gcd(x,y) * y; 22 } 23 inline void trans(lli dst[maxn][maxk],const lli sou[maxn][maxk],int now) { 24 for(int i=0;i<=n;i++) { 25 const int tar = lcm(i,now); 26 if( tar > n ) continue; 27 for(int j=0;j<k;j++) ( dst[tar][(j+now)%k] += sou[i][j] ) %= mod; 28 } 29 for(int i=0;i<=n;i++) 30 for(int j=0;j<k;j++) 31 ( dst[i][j] += sou[i][j] ) %= mod; 32 } 33 34 int main() { 35 static int T,cur; 36 scanf("%d",&T); 37 while(T--) { 38 memset(f,0,sizeof(f)) , cur = 0; 39 f[cur][0][0] = 1; 40 scanf("%d%d",&n,&k); 41 for(int i=1;i<=n;i++) { 42 cur ^= 1; 43 memset(f[cur],0,sizeof(f[1])); 44 trans(f[cur],f[cur^1],i); 45 } 46 printf("%lld\n",f[cur][n][0]); 47 } 48 return 0; 49 }