ZOJ Problem Set - 3662 Math Magic
1 #include <iostream> 2 #include <string.h> 3 #include <string> 4 #include <fstream> 5 #include <algorithm> 6 #include <stdio.h> 7 #include <vector> 8 #include <queue> 9 #include <set> 10 #include <cmath> 11 using namespace std; 12 const double eps = 1e-8; 13 const double pi=acos(-1.0); 14 const int INF=0x7fffffff; 15 unsigned long long uINF = ~0LL; 16 #define MAXN 100007 17 #define mod 1000000007 18 typedef long long LL; 19 int gcd(int a,int b) 20 { 21 return b==0?a:gcd(b,a%b); 22 } 23 int N,M,K; 24 int LCM(int a,int b) 25 { 26 return a*b/gcd(a,b); 27 } 28 LL ans; 29 int dp[2][1001][101],lcm[1001][1001]; 30 int pos[1001],num[1001]; 31 32 int main() 33 { 34 35 for(int i=1;i<=1000;i++) 36 for(int j=1;j<=1000;j++) 37 lcm[i][j]=LCM(i,j); 38 39 while(scanf("%d%d%d",&N,&M,&K)!=EOF) 40 { 41 ans=0;int cnt=0; 42 memset(pos,-1,sizeof(pos)); 43 for(int i=1;i<=M;i++) 44 if(M%i==0) 45 { 46 num[cnt]=i; 47 pos[i]=cnt++; 48 } 49 memset(dp[0],-1,sizeof(dp[0])); 50 dp[0][0][0]=1; 51 for(int i=1;i<=K;i++) 52 { 53 memset(dp[i&1],-1,sizeof(dp[i&1])); 54 for(int j=i-1;j<=N;j++) 55 { 56 for(int k=0;k<cnt;k++) 57 { 58 if(dp[(i+1)&1][j][k]==-1)continue; 59 for(int r=0;r<cnt&&j+num[r]<=N;r++) 60 { 61 int l=j+num[r]; 62 int s=lcm[num[r]][num[k]]; 63 if(s<=M&&pos[s]!=-1) 64 { 65 s=pos[s]; 66 if(dp[i&1][l][s]==-1)dp[i&1][l][s]=0; 67 dp[i&1][l][s]+=dp[(i+1)&1][j][k]; 68 if(dp[i&1][l][s]>=mod)dp[i&1][l][s]-=mod; 69 } 70 } 71 } 72 } 73 } 74 printf("%d\n",dp[K&1][N][pos[M]]==-1?0:dp[K&1][N][pos[M]]); 75 } 76 return 0; 77 }
dp,dp[i][j][k]表示取了i个数,和为j,LCM为状态k的时候的种数