山东OI2017-数字表格

O(n^2)——–>O(nlogn)
莫比乌斯、枚举约数
注意:逆元

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1000000007;
const int N = 1000000;
const int mx = 1000010;
int prime[80000],mu[mx],n,m,tot,ans;
int sf[mx],fib[mx],invf[mx],sg[mx],g[mx],invg[mx];
bool nop[mx];
int fun(int n,int k) {
    LL s=1;
    while (k) {
        if (k&1) s=s*n%mod;
        n=1LL*n*n%mod;
        k>>=1;
    }
    return (int)s;
}
int main() {
    mu[1]=fib[1]=fib[2]=sf[1]=g[1]=1;
    for (LL i=2; i<=N; ++i) {
        if (!nop[i]) {
            prime[tot++]=i;
            mu[i]=-1;
        }
        for (LL j=0; j<tot; ++j) {
            if (i*prime[j]>N) break;
            nop[i*prime[j]]=true;
            if (i%prime[j]==0) {
                mu[i*prime[j]]=0;
                break;
            } else mu[i*prime[j]]=-mu[i];
        }
        fib[i]=fib[i-1]+fib[i-2];
        if (fib[i]>=mod) fib[i]-=mod;
        sf[i]=1LL*sf[i-1]*fib[i]%mod;
        g[i]=1;
    }

    sg[1]=invg[0]=invg[1]=invf[0]=invf[1]=1;
    invf[N]=fun(sf[N],mod-2);
    for (int i=N; i>=2; --i)
        invf[i-1]=1LL*invf[i]*fib[i]%mod,
                  invf[i]=1LL*invf[i]*sf[i-1]%mod;
    for (int i=2; i<=N; ++i) {
        for (int j=1; i*j<=N; ++j)
            if (mu[j]==1)
                g[i*j]=1LL*g[i*j]*fib[i]%mod;
            else if (mu[j]==-1)
                g[i*j]=1LL*g[i*j]*invf[i]%mod;
        sg[i]=1LL*sg[i-1]*g[i]%mod;
    }
    invg[N]=fun(sg[N],mod-2);
    for (int i=N; i>=2; --i) invg[i-1]=1LL*invg[i]*g[i]%mod;

    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        ans=1;
        for (int last,i=1; i<=n; i=last+1)
            last=min(n/(n/i),m/(m/i)),
            ans=1LL*ans*fun(1LL*sg[last]*invg[i-1]%mod,1LL*(n/i)*(m/i)%(mod-1))%mod;
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值