熱身賽的1003,,水題啊,可是我折騰了一天。
首先要先發一次牌,得到一個順序,再根據這個順序獲得各個迴圈節的長度,對迴圈節求最小公倍數,便是總的最少移動次數.
題意是,n張牌每次發給k個人,再堆疊起來重新發:比如範例 10 3
原始狀態是: 1 2 3 4 5 6 7 8 9 10
一次過後: 10 7 4 1 8 5 2 9 6 3
第二次 3 2 1 10 9 8 7 6 5 4
第三次 4 7 10 3 6 9 2 5 8 1
第四次 1 2 3 4 5 6 7 8 9 10
根據做上一題的經驗我們知道只要第一次的牌,我們可以求得迴圈節,再根據迴圈節長度就可以做出了.
怎麼類比出第一次洗牌後的序列呢?
把
1 2 3
4 5 6
7 8 9
10 11 12
然後每次取一列.\
T_T,我卡在了最後求最小公倍數上了,我是先乘了再除了的,問了群神就醒悟過來"這樣會溢出"改成先除再乘,馬上就過了^_^
1 2 3 4 5 6 7 8 9 10用二維數組這樣存起來:
/*Problem ID:hdu 4259Meaning:Analyzing:置換群+lcm(迴圈節長度)*/#include <iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<vector>using namespace std;typedef struct even{int y1,y2,x;}even;#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define LL long long#define BUG puts("here!!!")#define STOP system("pause")#define file_r(x) freopen(x, "r", stdin)#define file_w(x) freopen(x, "w", stdout)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 808int A[maxn][maxn],V[maxn];LL gcd(LL a,LL b) {return a?gcd(b%a,a):b;}int main(){ int n,k; while(~scanf("%d%d",&n,&k)&&(n||k)){ int cnt=1,i; for(i=0;;i++){ for(int j=0;j<k;j++) A[i][j]=cnt++; if(cnt>n) break; } int M=1; for(int j=0;j<k;j++){ for(int m=i;m>=0;m--){ if(A[m][j]<=n&&A[m][j]) V[M++]=A[m][j]; } } int vis[maxn]; LL res=1,len; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++){ if(!vis[i]){ len=0; int t=i; while(1){ if(vis[t]) break; len++; vis[t]=1; t=V[t]; } res=res/gcd(len,res)*len; } } printf("%I64d\n",res); } return 0;}
再貼下標程,很贊0.0
#include <iostream>#include <vector>#include <cstring>using namespace std;long long gcd(long long a, long long b) { return a ? gcd(b % a, a) : b; }int A[1010];bool vis[1010];int main() { int N, K; for(cin >> N >> K; N || K; cin >> N >> K) { /* Compute the permutation induced by the shuffle. */ int M = 0; for(int i = 0; i < K && i < N; i++) { for(int j = (N - i - 1) / K * K + i; j >= 0; j -= K) { A[M++] = j;cout<<M-1<<" --> "<<A[M-1]<<endl; } } /* Compute the lcm of the cycle lengths of the permutation. */ long long res = 1; memset(vis, 0, sizeof(vis)); for(int i = 0; i < N; i++) { int x = i; int ln = 0; while(!vis[x]) { vis[x] = true; x = A[x]; ln++; } /* Careful to divide then multiply here. */ if(ln) res = res / gcd(res, ln) * ln; } cout << res << endl; }}