BZOJ 1965 快速幂 + 拓展欧几里得

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1965

AHOI2005 Day1

是一道找规律题…  不难发现初始为x的牌在经过m轮洗牌之后的位置为x*(2^k) % (n+1)。然后就是一个二元线性不定方程,拓欧解之即可。

方程为: (2^k)%(n+1)*x + (n+1)*y = L

// BZOJ 1965

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

 typedef long long LL;

 #define read(x) scanf("%lld", &x)

 LL n, m, L;

 void exgcd(LL a, LL b, LL &x, LL &y) {
 	
 	if (b==0) { x=1; y=0; return; }
 	exgcd(b, a%b, y, x);
 	y-=x*(a/b);
 }

 LL gcd(LL a, LL b) {
 	if (!(a%b)) return b;
 	return gcd(b, a%b);
 }

 LL quick_pow(LL a, LL n, LL mod) {
 	LL ret=1;
 	while (n>0) {
 		if (n%2) ret=(ret*a)%mod;
 		a=(a*a)%mod;
 		n/=2;
 	}
 	return ret;
 }

// p*x + n*y = L
int main()
{
	read(n); read(m); read(L);
	n++;
	LL p=quick_pow(2, m, n), d, x=0, y=0;
	d=gcd(p, n);
	p/=d; n/=d; L/=d;
        exgcd(p, n, x, y);
  	x=x*L%n;
	while (x<0) x+=n;
	printf("%lld\n", x);

	return 0;
}


posted @ 2015-12-10 20:37  Armeria  阅读(139)  评论(0编辑  收藏  举报