抽屉原理2--关于抽屉的循环问题

假设3位十进制数,目前,我所理解的抽屉是1001个这样的3位数里面一定会有两个相等,这一定是对的,但是,到目前为止,所有的程序中,我都是以如下方式处理:

		for(i=1; i<12; i++)
		{
			if(arr[i] == arr[0])
			{
				dis = i;
				break;
			}
		}

题目背景:


这显然不对,在这个程序当中,认定第一个数值在后面一定会重复出现,这在大部分情况下可行,却是错误的,下面一个设计用例就出现了问题:

对应代码为:

//Wrong answer 
#include<iostream>
using namespace std;

int main()
{
	int n,m;
	int val;
	cin>>n;
	int arr[12];
	int dis;
	
	while(n--)
	{
		cin>>m;	
		m = m%10;
		val = m;
		int i;
		for(i=0; i<12; i++)
		{
			arr[i] = val;
			val = val*m%10;			
		}
		for(i=1; i<12; i++)
		{
			if(arr[i] == arr[0])
			{
				dis = i;
				break;
			}
		}
		i = (m-1) % dis;
		cout<<arr[i]<<endl;
	}
	return 0;
}
修改方案:
//12 6这一组数据怎么老是通不过 
#include<iostream>
using namespace std;

int main()
{
	int a,b,sum;
	int dis;
	int arr[11000];
	
	while(cin>>a>>b)
	{
		if((a == 0)&&(b == 0))
		{
			return 0;
		}
		
		a = a % 1000;
		sum = a;
		
		for(int i=0; i<b; i++)
		{
			arr[i] = sum;
			sum = sum * a % 1000;
		}
		cout<<arr[b - 1]<<endl;
	}
	return 0;
}
这是很简单的处理方式,效率比较低。还有另外一种处理方式(尚待调试),算法思想是找出一个循环的长度以及循环开始的第一个数字:

//12 6这一组数据怎么老是通不过 
#include<iostream>
using namespace std;

int getCircle(int arr[])
{
	for(int i=0; i<1009; i++)
	{
		for(int j=i + 1; j<1010; j++)
		{
			if(arr[j] == arr[i])
			{
				return j - i;
			}
		}
	}
	return 0;
}


int main()
{
//	int getCircle(int arr[], int *n);
	int a,b,sum;
	int dis;
	int arr[1010];
	
	while(cin>>a>>b)
	{
		if((a == 0)&&(b == 0))
		{
			return 0;
		}
		
		a = a % 1000;
		sum = a;
		
		for(int i=0; i<1010; i++)
		{
			arr[i] = sum;
	//		cout<<arr[i]<<"	";
			sum = sum * a % 1000;
		}
	//	cout<<endl;
		 
		 /*
		for(int i=0; i<1009; i++)
		{
			for(int j=0; j<1010; j++)
			{
				if(arr[i] == arr[0])
				{
					
				}
			}
			if(arr[i] == arr[0])
			{
				dis = i;
				//cout<<"我被执行了\n";
				//cout<<"dis"<<endl;
				break;
			}
		}
		*/
//		int *st = 0;
		int cicleT = getCircle(arr);
		cout<<cicleT<<endl;
		dis = (b-1) % dis; 
		cout<<arr[dis]<<endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值