1. 程式人生 > >SDOI2017 數字表格

SDOI2017 數字表格

題目描述:

f為斐波那契數列。

T組詢問,每次給出表格的n、m。表中(i,j)為gcd(i,j),求表中所有數之積mod 1e9+7的值。

T<=1e5,n,m<=1e9

題解:

反演。

程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 1000500
#define MOD 1000000007
#define ll long long
int t,n,m;
int pri[N],cnt,mu[N];
bool vis[N];
ll f[N][
2],g[N],G[N][2]; ll fastpow(ll x,ll y) { ll ret = 1ll; while(y) { if(y&1)ret=ret*x%MOD; x=x*x%MOD; y>>=1; } return ret; } ll inv(ll x) { return fastpow(x,MOD-2); } void init() { mu[1]=1; f[1][0]=f[1][1]=1; g[1]=1; for(int i=2;i<=1000000
;i++) { f[i][1]=(f[i-1][1]+f[i-2][1])%MOD; f[i][0]=inv(f[i][1]); if(!vis[i]) { pri[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt&&i*pri[j]<=1000000;j++) { vis[i*pri[j]]=1; if(i%pri[j])mu[i*pri[j]]=-mu[i];
else break; } g[i]=1; } G[0][1]=G[0][0]=1; for(int i=1;i<=1000000;i++) { if(!mu[i])continue; for(int j=1;i*j<=1000000;j++) { (g[i*j]*=f[j][mu[i]>0?1:0])%=MOD; } } for(int i=1;i<=1000000;i++) { G[i][1]=G[i-1][1]*g[i]%MOD; G[i][0]=inv(G[i][1]); } } int main() { init(); scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); if(n>m)swap(n,m); ll ans = 1ll; for(int i=1,nxt;i<=n;i=nxt+1) { nxt = min(n/(n/i),m/(m/i)); ll tmp = G[nxt][1]*G[i-1][0]%MOD; ans=ans*fastpow(tmp,1ll*(n/i)*(m/i)%(MOD-1))%MOD; } printf("%lld\n",ans); } return 0; }