description:
一开始有两个数A和B,进行K轮游戏,每一轮可能有两种情况:
- 若 A≤B,本***作后 B′=B−A,A′=A+A.
 - 若 B<A, 本***作后 A′=A−B,B′=B+B.
 
请输出 K轮游戏后 min(A,B)的值。
| A,B≤ | K≤ | |
|---|---|---|
| 20% | 103 | 109 | 
| 20% | 106 | 109 | 
| 20% | 108 | 109 | 
| 20% | 109 | 107 * | 
| 20% | 109 | 109 | 
solution:
-  
k≤107
直接 O(k)暴力即可 -  
A,B≤103andA,B≤106
 
A+B是一个循环节的长度,这样就可以通过直接除掉循环节来减少运算次数,但是A,B大了之后循环节就枚举不出来了。
- A,B<=108
 
传统的找循环节⽅方法空间是 O(A+B)会超过内存限制
可以⽤用bitset把内存变成 O((A+B)/32)
bitset<200000000>F;
- A,B<=109
 
设 S=A+B
若 A<=B(即S-A),则A’ = 2A = 2A mod S
若 A>B,则A’ = A - (S - A) = 2A - S = 2A mod S
所以答案为 A∗2KmodS
code:
刚开始的逐步骗分代码( 65pts):
//请输出k次后min(A,B)的值 
#include<cstdio>
using namespace std;
int min(int a,int b)
{
	if(a<=b)
	{
		return a;
	}
	else
	{
		return b;
	}
}
int x[10000005],y[10000005];
long long a,b,k;
void ANS()
{
	int flag=0;
	x[0]=a;
	y[0]=b;
	long long tmp=0,num=0;
	for(long long i=1;i<=k;i++)
	{
		if(x[i-1]<=y[i-1])
		{
			y[i]=y[i-1]-x[i-1];
			x[i]=x[i-1]*2;
		}
		else
		{
			x[i]=x[i-1]-y[i-1];
			y[i]=y[i-1]*2;
		}
		if(i==1)tmp=x[i];
		if(i!=1&&x[i]==tmp)
		{
			num=i;
			flag=1;
			break;
		}
	}
	if(flag==0)
	{
		printf("%d\n",min(x[k],y[k]));
		return;
	}
	num--;
	long long ans=k%num;
	printf("%d\n",min(x[ans],y[ans]));
}
int main()
{
	//freopen("game.in","r",stdin);
	//freopen("game.out","w",stdout); 
	scanf("%lld%lld%lld",&a,&b,&k);
	if(k<=10000000)//20%
	{
		for(long long i=1;i<=k;i++)
		{
			if(a<=b)
			{
				b=b-a;
				a=a+a;
			}
			else
			{
				a=a-b;
				b=b+b;
			}
		}
		printf("%d\n",min(a,b));
		return 0;
	}
	if(a<=1000&&b<=1000)//20%
	{
		ANS();
		return 0;
	}
	if(a<=1000000&&b<=1000000)//20%
	{
		ANS();
		return 0;
	}
	if(a<=100000000&&b<=100000000)//20% 
	{
		ANS();
		return 0;
	}
	else//听天由命 
	{
		ANS();
		return 0;
	}
} 
//955 812 828145516
/* 955253431 806956091 10000000 a=135061684 */
  正解代码:
#include<cstdio>
using namespace std;
long long sqr(long long x)
{
	return x*x;
}
long long ksm(long long x,long long y,long long p)
{
	if(y==0)return 1;
	if(y%2==1)
	{
		return x*ksm(x,y-1,p)%p;
	}
	else
	{
		return sqr(ksm(x,y/2,p))%p;
	}
}
long long min(long long x,long long y)
{
	if(x<y)return x;
	else return y;
}
int main()
{
	//printf("%d\n",ksm(2,5,10));
	long long a,b,k;
	scanf("%lld%lld%lld",&a,&b,&k);
	long long ans=a*ksm(2,k,a+b)%(a+b);
	printf("%lld\n",min(ans,a+b-ans));
	return 0;
} 



京公网安备 11010502036488号