「luogu3704」[SDOI2017]数字表格

莫比乌斯反演,其中一些处理比较套路

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=1000010,mod=1000000007;
 5 ll n,m,u[N],f[N],fi[N],invfi[N];
 6 int p[N],tot,lim=1000000;
 7 bool isp[N];
 8 ll qpow(ll x,ll y){
 9     ll res=1;
10     while(y){
11         if(y&1) res=res*x%mod;
12         x=x*x%mod,y>>=1;
13     }
14     return res;
15 }
16 void pre(){
17     f[0]=1,u[1]=1,fi[1]=1,invfi[1]=1,f[1]=1;
18     for(int i=2;i<=lim;i++){
19         f[i]=fi[i]=(fi[i-1]+fi[i-2])%mod;
20         invfi[i]=qpow(fi[i],mod-2);
21     }
22     for(int i=2;i<=lim;i++){
23         if(!isp[i]) p[++tot]=i,u[i]=-1;
24         for(int j=1;j<=tot&&1LL*i*p[j]<=lim;j++){
25             isp[i*p[j]]=1;
26             if(i%p[j]) u[i*p[j]]=-u[i];
27             else{u[i*p[j]]=0;break;}
28         }
29         if(u[i]) for(int j=1;j*i<=lim;j++)
30             f[i*j]=f[i*j]*(u[i]==1?fi[j]:invfi[j])%mod;
31     }
32     for(int i=2;i<=lim;i++) f[i]=f[i]*f[i-1]%mod;
33     return;
34 }
35 void solve(){
36     scanf("%lld%lld",&n,&m);
37     if(n>m) swap(n,m);
38     ll l=1,r,res=1;
39     while(l<=n){
40         r=min(n/(n/l),m/(m/l));
41         ll temp=f[r]*qpow(f[l-1],mod-2)%mod;
42         res=res*qpow(temp,(n/l)*(m/l)%(mod-1))%mod;
43         l=r+1;
44     }
45     printf("%lld\n",res);
46     return;
47 }
48 int main(){
49     pre();
50     int T;scanf("%d",&T);
51     while(T--) solve();
52     return 0;
53 }

 

posted @ 2018-03-16 11:18  Cupcake  阅读(128)  评论(0编辑  收藏  举报