【题解】[SDOI2017]数字表格

Link

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN=1e6;
int T,n,m,f[MAXN+10],g[MAXN+10],inv[MAXN+10];
const int mod=1e9+7;
inline int add(int x,int y){return (x+y+mod)%mod;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int mul_(int x,int y){return 1ll*x*y%(mod-1);}
bitset<MAXN+10>vis;
int p[MAXN+10],cnt,mu[MAXN+10],ans;
inline int qpow(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=mul(res,x);
		x=mul(x,x);y>>=1;
	}
	return res;
}
void pretreatment(int G){
	mu[1]=1;f[1]=1;inv[1]=1;g[0]=g[1]=1;vis[1]=1;
	for(int i=2;i<=G;++i){
		f[i]=f[i-1]+f[i-2];f[i]%=mod;
		inv[i]=qpow(f[i],mod-2);g[i]=1;
		if(!vis[i])p[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*p[j]<=G;++j){
			vis[i*p[j]]=1;
			if(i%p[j]==0)break;
			mu[i*p[j]]=-mu[i];
		}
	}
	//for(int i=1;i<=G;++i)mu[i]+=mu[i-1];
	for(int i=1;i<=G;++i){
		if(!mu[i])continue;
		for(int j=i;j<=G;j+=i){
			g[j]=1ll*g[j]*(mu[i]==1?f[j/i]:inv[j/i])%mod;
		}
	}
	for(int i=2;i<=G;++i)g[i]=mul(g[i],g[i-1]);
}
int solve(int N,int M){
	int res=1;
	for(int l=1,r;l<=min(N,M);l=r+1){
		r=min(N/(N/l),M/(M/l));
		int PP=mul(g[r],qpow(g[l-1],mod-2));
		res=mul(res,qpow(PP,mul_(N/l,M/l)));
	}
	return res;
}
signed main(){
	//freopen("1.in","r",stdin);
	//freopen("test.out","w",stdout);
	pretreatment(1000000);
	scanf("%lld",&T);
	while(T--){
		scanf("%lld%lld",&n,&m);
		if(n>m)swap(n,m);
		ans=solve(n,m);
		printf("%lld
",(ans+mod)%mod);
	}
	return 0;
}

菜鸡笔者推到枚举(kd)时没有想到,于是悲惨爆零)

注意函数的筛法,以及指数取余的时候可以套用欧拉定理。

原文地址:https://www.cnblogs.com/h-lka/p/13370739.html