码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1721

时间:2014-10-16 17:26:52      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   for   sp   div   on   log   amp   

好像不需要用到开方什么的。。。

可以知道,一副牌即是一个循环,那么,由于GCD(L,K)=1,所以一次洗牌后,亦是一个循环。其实,K次洗牌等于是T^(2^K)了。既然是循环,必定有周期。那么,周期是多少呢?以例子为例:1->4->6->2->7->3->5。其实对于第一个数(从零始)4,总会有先后移了2^a次方而回到原点,此时就是一个周期了。即是求2^a=1(mod n)。求出最小的a即可知道周期。s%a=t.那么,即是差a-t个状态就可以回到初始的了。

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

int num[1005];
int tmp[1005];
int ans[1005];

int control(int n){
	int ans=1;
	for(int i=1;i<=n-1;i++){
		ans=(ans*2)%(n);
		if(ans==1)
		return i;
	}
}

int quick(int s,int n){
	int res=1; int p=2;
	while(s){
		if(s&1) res=(res*p)%n;
		s>>=1;
		p=(p*p)%n;
	}
	return res;
}

int main(){
	int n,s,cnt,k,pos;
	while(scanf("%d%d",&n,&s)!=EOF){
		for(int i=1;i<=n;i++)
		scanf("%d",&num[i]);
		int cy=control(n);
	//	cout<<"cy="<<cy<<endl;
		tmp[0]=1;
		cnt=0; k=1;
		while(num[k]!=1){
			tmp[++cnt]=num[k];
			k=num[k];
		}
	/*	for(int i=0;i<n;i++)
		cout<<tmp[i]<<‘ ‘;
		cout<<endl;*/
		s=s%cy;
		s=cy-s;
	//	cout<<"s="<<s<<endl;
		s=quick(s,n);
	//	cout<<"s="<<s<<endl;
		ans[0]=tmp[0];
		pos=0;
		for(int i=1;i<n;i++){
			ans[i]=tmp[pos=(pos+s)%n];
		}
		for(int i=1;i<=n;i++){
			num[ans[i-1]]=ans[i%n];
		}
		for(int i=1;i<=n;i++){
			printf("%d\n",num[i]);
		}
	}
	return 0;
}

  

POJ 1721

标签:blog   io   os   for   sp   div   on   log   amp   

原文地址:http://www.cnblogs.com/jie-dcai/p/4028619.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!