CF185D
大胆猜测,所有数的最大公约数一定很小:偶数时为 \(1\),奇数时为 \(2\)。设两个正整数 \(n,m\) 且 \(n<m\),最大公约数 \(\gcd(k^{2^n}+1,k^{2^m}+1)=d\),则有 \(k^{2^n}\equiv k^{2^m} \equiv -1\pmod d,k^{2^{n+1}} \equiv (k^{2^{n+1}})^{\frac{2^m}{2^{n+1}}} \equiv k^{2^m} \equiv 1 \pmod d\),故 \(-1 \equiv 1 \pmod d\),即 \(d\) 只能为 \(1\) 或 \(2\),当且仅当 \(k=1\) 时 \(d=2\)。
现在要求 \((k^{2^l}+1)(k^{2^{l+1}}+1)\cdots(k^{2^r}+1)\)。这个式子的意义可以理解为二进制上每一位选或不选,那么每一个 \(k\) 的幂一定恰好出现一次,则答案为 \(\dfrac{k^{2^{r+1}}-1}{k^{2^l}-1}\)。比如 \((k^1+1)(k^2+1)(k^4+1)=k^0+k^1+\cdots+k^7=\dfrac{k^8-1}{k-1}\)(\(l,r+1\) 的两个分式可以消去分子)。直接使用逆元计算即可。以下是特殊情况:
- 分母为 \(0\) 时,\(k^{2^l} \equiv 1 \pmod p\),后面 \(k\) 的幂也是同样的结果,直接输出 \(2^{r-l+1}\) 即可。
- 使用费马小定理减小指数,注意此时模数为 \(p-1\)(\(p=2\) 时不符合使用条件,直接特判即可)。
- 如果 \(k\) 是奇数,最后再乘上 \(2^{r-l}\) 的逆元即可(乘多的部分)。
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
int k,l,r,p,n;
int qp(int a,int b,int mod){
a=(a%mod+mod)%mod;
int c=1;
while(b){
if(b&1)c=c*a%mod;
b>>=1;
a=a*a%mod;
}
return c;
}
int calc(int x){
if(k%p==0)return 0;
n=qp(2,x+1,p-1);
// cout<<n<<endl;
return qp(k,n,p);
}
signed main(){
int T;
cin>>T;
while(T--){
cin>>k>>l>>r>>p;
if(p==2){
if(k%2)cout<<0<<'\n';
else cout<<1<<'\n';
continue;
}
if(calc(l-1)==1){
if(k&1)cout<<qp(2,r-l+1,p)*qp(qp(2,r-l,p),p-2,p)%p<<'\n';
else cout<<qp(2,r-l+1,p)<<'\n';
continue;
}
if(k&1)cout<<((calc(r)-1)*qp((calc(l-1)-1),p-2,p)%p*qp(qp(2,r-l,p),p-2,p)%p+p)%p<<'\n';
else cout<<((calc(r)-1)*qp((calc(l-1)-1),p-2,p)%p+p)%p<<'\n';
}
return 0;
}
我们会走到一起的。

浙公网安备 33010602011771号