正题
题目链接:https://www.luogu.com.cn/problem/P3704
题目大意
TTT组询问,给出n,mn,mn,m求∏i=1n∏j=1mFbigcd(i,j)\prod_{i=1}^n\prod_{j=1}^mFbi_{gcd(i,j)}i=1∏nj=1∏mFbigcd(i,j)
其中FbixFbi_xFbix表示第xxx项斐波那契数列。
解题思路
答案就是∏x=1nFbix∑i=1n∑j=1m[gcd(i,j)==x]\prod_{x=1}^nFbi_x^{\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==x]}x=1∏nFbix∑i=1n∑j=1m[gcd(i,j)==x]
然后上反演就是∏x=1nFbix∑x∣d⌊nd⌋⌊md⌋μ(dx)\prod_{x=1}^nFbi_x^{\sum_{x|d}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\mu(\frac{d}{x})}x=1∏nFbix∑x∣d⌊dn⌋⌊dm⌋μ(xd)
同样是提出来∏d=1n(∏x∣dnFbixμ(dx))⌊nd⌋⌊md⌋\prod_{d=1}^n(\prod_{x|d}^nFbi_x^{\mu(\frac{d}{x})})^{\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor}d=1∏n(x∣d∏nFbixμ(xd))⌊dn⌋⌊dm⌋
然后预处理∏x∣dnFbixμ(dx)\prod_{x|d}^nFbi_x^{\mu(\frac{d}{x})}∏x∣dnFbixμ(xd)的前缀积再整除分块即可
时间复杂度O(Tn+m)O(T\sqrt{n+m})O(Tn+m)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e6+10,P=1e9+7;
ll T,n,m,cnt,ans;bool v[N];
ll mu[N],f[N],g[N],pri[N],inv[N];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
void Prime(){mu[1]=f[1]=inv[1]=g[0]=g[1]=1;for(ll i=2;i<N;i++){if(!v[i])pri[++cnt]=i,mu[i]=-1;g[i]=1;for(ll j=1;j<=cnt&&i*pri[j]<N;j++){v[i*pri[j]]=1;if(i%pri[j]==0)break;mu[i*pri[j]]=mu[i]*mu[pri[j]];}}for(ll i=2;i<N;i++)f[i]=(f[i-1]+f[i-2])%P,inv[i]=power(f[i],P-2);for(ll i=1;i<N;i++){if(!mu[i])continue;for(ll j=i;j<N;j+=i){if(mu[i]==1)(g[j]*=f[j/i])%=P;else (g[j]*=inv[j/i])%=P;}}inv[1]=inv[0]=1;for(ll i=2;i<N;i++)g[i]=g[i]*g[i-1]%P,inv[i]=power(g[i],P-2);return;
}
int main()
{Prime();scanf("%lld",&T);while(T--){scanf("%lld%lld",&n,&m);ans=1;if(n>m)swap(n,m);for(ll l=1,r;l<=n;l=r+1){r=min(n/(n/l),m/(m/l));ll mul=g[r]*inv[l-1]%P;ans=ans*power(mul,(n/l)*(m/l)%(P-1))%P;}printf("%lld\n",ans);}
}