codeforces185D.Visit of the Great

6 篇文章 0 订阅

http://codeforces.com/contest/185/problem/D

题意: 求LCM(k^(2^l)+1, k^(2^(l+1)) + 1, k^(2^(l+2)) + 1, ... , k^(2^r) + 1) mod p. l, r都很大,不能直接求。

思路:假设x=k^(2^l)+1,那么k^(2^(l+1))+1 = (x-1)^2+1 = x^2-2^x+2, 而gcd(x, x^2-2^x+1)=gcd(x, 2),所以gcd(k^(2^l)+1, k^(2^(l+1)) + 1)要么为1,要么为2。显然就是k的奇偶问题。知道了GCD,LCM就好求了。总的来说,结果大致可以归结为:

1.若k是奇数,答案就是(k^(2^l)+1)(k^(2^(l+1)) + 1)...(k^(2^r)+1)/2^(r - l)

2.若k是偶数,答案就是(k^(2^l)+1)(k^(2^(l+1)) + 1)...(k^(2^r)+1)

第二个关键在于怎么求(k^(2^l)+1)(k^(2^(l+1)) + 1)...(k^(2^r)+1)

其实把这条式化开整理一下:(k^(2^l)+1)(k^(2^(l+1)) + 1)...(k^(2^r)+1) = 1 + k^(2^l) + k^(2*(2^l)) + k^(2^(3*(2^l))) + ... + k^(2^((2^(r-l+1)-1)*(2^l)))

=右边就是一个等比公式,直接用公式代进去就可以了

公式有除法运算,求余的话要注意有可能跟p不是互素,不过很容易想到当且仅当p|(k^(2^l)-1)是才出现这种情况,特殊处理一下就行了。

最后如果k是奇数在除以一下2^(r-l)即可。

代码:


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

#define sqr(x) ((x) * (x))
#define two(x) (1 << (x))
#define ord(x, y, z) ((x) <= (y) && (y) <= (z))
#define X first
#define Y second

typedef long long LL;
typedef pair<int, int> pair2;

const int N = 1;
const double eps = 1e-9;
const int oo = 1000000000;

int k, p;
LL l, r;

int pow2(int x, LL y, int p) {
	if (y == 0) { 
		return 1 % p;
	} else if (y == 1) {
		return x % p;
	} else {
		int t = pow2(x, y >> 1, p);
		t = (LL)t * t % p;
		if (y & 1) {
			return (LL)t * x % p;
		} else {
			return t;
		}
	}
}

int sum(LL x) {
	return (LL)(pow2(k, pow2(2, x + 1, p - 1), p) - 1) * pow2(k - 1, p - 2, p) % p;
}

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		cin >> k >> l >> r >> p;
		int a = 1;
		if (k % p) {
			a = pow2(2, r - l + 1, p) % p;
			if (pow2(k, pow2(2, l, p - 1), p) != 1) {
				a = (LL)sum(r) * pow2(sum(l - 1), p - 2, p) % p;
			}
		}
		if (k & 1) {
			a = (LL)a * pow2(pow2(2, r - l, p), p - 2, p) % p;
		}
		a = (a + p) % p;
		printf("%d\n", a);
	}
	return 0;
}


半年没写题解了……有空的时候上去吹吹也不错,哈哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值