前言
这nm sb hexo 我{{...}}
这种情况报错改了调了一个多小时
正文
人话版本:
求 Πi=1nΠj=1mf(gcd(i,j))
我们转化一下,先枚举 gcd
Πd=1nΠi=1⌊dn⌋Πj=1⌊dm⌋f(d)ϵ(gcd(i,j))
把乘法放在指数上
Πd=1nf(d)∑i=1⌊dn⌋∑j=1⌊dm⌋ϵ(gcd(i,j))
然后反演 μ 函数
$ \large \operatorname{\Pi}{d=1}^{n}\limits f(d)^{\operatorname{\sum}{k=1}^{\lfloor\frac{m}{d}\rfloor}\limits\operatorname{\sum}{i=1}^{\lfloor\frac{n}{kd}\rfloor}\limits\operatorname{\sum}{j=1}^{\lfloor\frac{m}{kd}\rfloor}\limits \mu(k)}$
然后移出来
$ \large \operatorname{\Pi}{d=1}^{n}\limits \operatorname{\Pi}{k=1}^{\lfloor\frac{m}{d}\rfloor}\limits f(d)^{\mu(k) \operatorname{\sum}{i=1}^{\lfloor\frac{n}{kd}\rfloor}\limits\operatorname{\sum}{j=1}^{\lfloor\frac{m}{kd}\rfloor}\limits }$
令 kd=T
可以得到
$ \large \operatorname{\Pi}{T=1}^{n}\limits \operatorname{\Pi}{d|T}^{}\limits f(d)^{\mu(\frac{T}{d}) \operatorname{\sum}{i=1}^{\lfloor\frac{n}{T}\rfloor}\limits\operatorname{\sum}{j=1}^{\lfloor\frac{m}{T}\rfloor}\limits }$
可以 O(nlogn) 地预处理
Πd∣Tf(d)μ(dT)
然后外面就是个整除分块,然后做完了,记得预处理逆元,不然复杂度可能会假
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| #include<stdio.h> #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<vector> #include<set> #include<map> #include<algorithm>
#define int long long
using namespace std;
const int maxn=1001000; const int modp=1e9+7; const int loopn=1e6;
int mu[maxn],p[maxn],inp[maxn],cnt; int f[maxn],tc[maxn],n,m; int _f[maxn],tmp[maxn];
int ksm(int x,int y) { int ans=1; while(y) { if(y&1) ans=ans*x%modp; x=x*x%modp; y>>=1; } return ans; }
inline void _prework(int n) { int i,j; mu[1]=1; for(i=2;i<=n;i++) { if(!inp[i]) p[++cnt]=i,mu[i]=-1; for(j=1;j<=cnt&&i*p[j]<=n;j++) { inp[i*p[j]]=1; if(i%p[j]==0) { mu[i*p[j]]=0; break; } mu[i*p[j]]=-mu[i]; } } f[1]=f[2]=1; for(i=3;i<=n;i++) f[i]=(f[i-1]+f[i-2])>modp?f[i-2]+f[i-1]-modp:f[i-1]+f[i-2]; for(i=1;i<=n;i++) tmp[i]=1,_f[i]=ksm(f[i],modp-2); for(i=1;i<=n;i++) for(j=1;i*j<=n;j++) { if(mu[j]>=0) tmp[i*j]=tmp[i*j]*ksm(f[i],mu[j])%modp; else tmp[i*j]=tmp[i*j]*_f[i]%modp; } for(i=1;i<=n;i++) f[i]=tmp[i]; f[0]=1; _f[0]=1; for(i=1;i<=n;i++) f[i]=(f[i]*f[i-1])%modp,_f[i]=ksm(f[i],modp-2); }
inline void getans(int n,int m) { int i,j,ans=1; for(i=1;i<=min(n,m);i=j+1) { j=min(n/(n/i),m/(m/i)); ans=ans*ksm((f[j]*_f[i-1])%modp,(n/i)*(m/i)%(modp-1))%modp; } cout<<ans<<endl; }
signed main() { ios::sync_with_stdio(false); register int i,j; _prework(loopn); int t; cin>>t; while(t--) { cin>>n>>m; getans(n,m); } return 0; }
|