1297. 猴子舞

TAG 动态规划

 

原本想用数学方法解, 构造了一下, 只能解出部分答案, 显然是有问题的....

 

我的经验就是, 对于这种"数学题", 一般是可以计算机的办法"暴力"解的, 暴搜或者dp吧..

 

先理清题意, 对于题目描述的图, 如果能保证图连通, 那就是一个环了. 因为连通性不作要求,所以实际上可以分为1个或多个环. 当然, 这里每个环至少包含2个"圈".

就是求把n分成若干份,使其的最大公约数最大.

dp[i][j]表示i个圈, 分成j个环

dp[i][j] = max{ dp[x][j-1] * (i-x) / gcd( dp[x][j-1], (i-x) },  (j-1)*2 <= x <= i-2

 

0.93s, 有点危险, 看了status, 有 0.00 sec的,应该是打表的吧, 有0.24 sec的, 难道有效率更高的方法? 我再想想..

hits: 注意用long long 这种推算类的题目结果经常很大, 还好这道还不用高精度...

// source code of submission 726741, Zhongshan University Online Judge System #include <stdio.h> #include <memory.h> const int N=250; long long dp[N][N/2]; long long gcd(long long x, long long y) { if ( x%y==0 ) { return y; } return gcd( y, x%y); } long long ans, tmp; int n; int main(int argc, char *argv[]) { memset(dp, 0, sizeof(dp) ); for (int i=0; i<N; ++i) { dp[i][0]=i+1; } for (int k=1; k<N/2; ++k) { for (int i=(k+1)*2-1; i<N; ++i) { dp[i][k]=dp[i-2][k-1]*2/gcd(dp[i-2][k-1], 2); for (int j=i-3; j>=k*2-1; --j) { tmp=dp[j][k-1]*(i-j)/gcd(dp[j][k-1], i-j); if ( dp[i][k]<tmp ) { dp[i][k]=tmp; } } } } while ( scanf("%d", &n), n!=0 ) { ans=dp[n-1][0]; for (int i=1; i<n/2; ++i) { if (ans<dp[n-1][i]) { ans=dp[n-1][i]; } } printf("%lld/n", ans); } return 0; }

你可能感兴趣的:(1297. 猴子舞)