前言
这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)
然后外面就是个整除分块,然后做完了,记得预处理逆元,不然复杂度可能会假
| 12
 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;
 }
 
 
 |