P10084 [GDKOI2024 提高组] 计算 题解
- 题目传送门
- 前置知识:单位根反演
先考虑怎么求
所以
考虑用生成函数做,易得答案为:
套一下单位根反演的式子
注意到
考虑右边这个括号里的东西怎么求,由因式分解知识可得
然后直接
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define mxn 10000003
#define md 998244353
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
ll power(ll x,int y){
ll ans=1;
for(;y;y>>=1){
if(y&1)ans=ans*x%md;
x=x*x%md;
}
return ans;
}
ll power1(ll x,int y){
ll ans=1;
for(;y;y>>=1){
if(y&1)ans*=x;
x*=x;
}
return ans;
}
inline int gcd(int x,int y){
while(y^=x^=y^=x%=y);
return x;
}
int t,m,a,b,c,d,tot,p[mxn],f[mxn],phi[mxn];
ll l,r,n,g,ans;
void init(int n){
phi[1]=1;
rep(i,2,n){
if(!f[i])f[i]=p[++tot]=i,phi[i]=i-1;
rep(j,1,tot){
if(p[j]>f[i]||p[j]>n/i)break;
f[p[j]*i]=p[j];
phi[p[j]*i]=i%p[j]?phi[i]*(p[j]-1):phi[i]*p[j];
}
}
}
signed main(){
init(1e7);
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d%d",&m,&a,&b,&c,&d);
l=a==0||b==0?0:power1(m,gcd(a,b));
r=power1(m,gcd(c,d));
n=(r-l)/m;
ans=0;
g=power(2,n%(md-1));
rep(k,1,sqrt(m))if(m%k==0){
if(k&1)ans=(ans+phi[k]*power(g,m/k))%md;
if(m/k!=k){
if((m/k)&1)ans=(ans+phi[m/k]*power(g,k))%md;
}
}
printf("%lld\n",(ans*power(m,md-2)%md+md)%md);
}
return 0;
}