HDU 4259 Double Dealing 8-25日网络赛1003题
第一次遇到20s的题,果断暴力,贡献多个TLE, 水题也不是完全水的,必须要适当的优化一下,学习了。
View Code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define lld __int64 lld gcd(lld a, lld b) //最大公约数 { return a ? gcd(b%a, a) : b; } int n, k; int a[802]; bool vis[802]; int main() { int i, j; while( ~scanf("%d%d", &n, &k) &&(n || k) ) { int fx, fy, x, y; // 最后一位数字n-1的行列 ,数字从0开始 fx = (n - 1) / k + 1; fy = (n - 1) % k + 1; for(i = 0; i < n; i++) { //数字i所在的行列 x = i / k + 1; y = i % k + 1; //行列右下角不一定有数字,矩阵有没填满的情况 //计算出一次洗牌后i数字的位置,存在a[i]里面 if(y <= fy) a[i] = fx * y - x; else a[i] = (fx - 1) * y + fy - x; } memset(vis, 0, sizeof(bool) * n); int j; lld tmp, ans = 1; //对每个数找周期,并求这些周期的最小公倍数。 for(i = 0; i < n; i++) { j = i; tmp = 0; while(!vis[j])//出现以前出现过的数字,那么这个j的周期必然和 出现过的数字的周期是相同的,所以可以跳过 { vis[j] = 1; j = a[j]; tmp++; } if(tmp) { if(ans == 1) ans = tmp; else ans = ans/gcd(tmp, ans) * tmp; } } printf("%I64d\n", ans); } return 0; }


浙公网安备 33010602011771号