codeforces185D.Visit of the Great

来源:互联网 发布:编程 hack是什么意思 编辑:程序博客网 时间:2024/06/05 18:36

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 secondtypedef 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;}


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