P3704 [SDOI2017]数字表格

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define maxn 1000009
#define N maxn+10
#define M 1000000007
using namespace std;
int n,m;
int q;
LL ksm(LL a,LL p){
	LL ans=1;
	for(;p;p>>=1,a=a*a%M){
		if(p&1)ans=ans*a%M;
	}
	return ans;
}

inline LL inv(LL a){
	return ksm(a,M-2);
}

int vis[N];
int mu[N];
int prime[N],cnt;
LL f[N];
LL g[N];
LL invg[N];
int shake(){
	mu[1]=1;vis[1]=1;
	for(int i=2;i<=maxn;++i){
		if(!vis[i]){
			prime[++cnt]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=maxn;++j){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				mu[i*prime[j]]=0;
				break;
			}
			mu[i*prime[j]]=-mu[i];
		}
	}
	
	f[1]=f[2]=1;
	for(int i=3;i<=maxn;++i)f[i]=(f[i-1]+f[i-2])%M;
	for(int i=0;i<=maxn;++i)g[i]=1;
	for(int d=1;d<=maxn;++d){
		LL inverse=inv(f[d]);
		for(int k=1;k*d<=maxn;++k){
			if(mu[k]==1){
				g[k*d]=g[k*d]*f[d]%M;
			}
			if(mu[k]==-1){
				g[k*d]=g[k*d]*inverse%M;
			}
		}
	}
	for(int i=2;i<=maxn;++i)g[i]=g[i]*g[i-1]%M;
	for(int i=0;i<=maxn;++i)invg[i]=inv(g[i]);
}

inline int read(){
	int r=0,k=1;
	char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
	for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
	return r*k;
}

int main(){
	//freopen("product.in","r",stdin);
	//freopen("product.out","w",stdout);
	shake();
	
	q=read();
	while(q--){
		n=read();m=read();
		if(n>m)swap(n,m);
		int last;LL ans=1;
		for(int i=1;i<=n;i=last+1){
			last=min(n/(n/i),m/(m/i));
			ans=ans*ksm(g[last]*invg[i-1]%M,(LL)(n/i)*(m/i))%M;
		}
		printf("%d\n",ans);
	}
	return 0;
}

  

posted @ 2017-08-11 19:08  ws_zzy  阅读(314)  评论(2编辑  收藏  举报