码迷,mamicode.com
首页 > 其他好文 > 详细

codevs 5962 [SDOI2017]数字表格

时间:2017-04-12 03:52:58      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:main   while   code   printf   bool   input   ret   media   body   

技术分享

输入描述 Input Description

技术分享

 [题解]

技术分享

对于蓝色部分预处理前缀积。

然后在用除法分块搞一下。

O(Q*sqrt(min(n,m))*logn+nlogn)

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const ll mod=1e9+7;
int T,n,m,tot,mu[N],prime[N/3];bool check[N];
ll f[N],invf[N],g[N];
ll fpow(ll a,ll p){
    ll res=1;
    for(;p;p>>=1,a=a*a%mod) if(p&1) res=res*a%mod;
    return res;
}
void pre(){
    mu[1]=1;n=1e6;
    for(int i=2;i<=n;i++){
        if(!check[i]) prime[++tot]=i,mu[i]=-1;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            check[i*prime[j]]=1;
            if(!(i%prime[j])){mu[i*prime[j]]=0;break;}
            else mu[i*prime[j]]=-mu[i];
        }
    }
    f[1]=1;
    for(int i=2;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod;
    for(int i=1;i<=n;i++) invf[i]=fpow(f[i],mod-2);
    fill(g,g+n+1,1);
    for(int i=1;i<=n;i++){
        for(int j=1;i*j<=n;j++){
            if(mu[j]){
                g[i*j]=g[i*j]*(mu[j]==1?f[i]:invf[i])%mod;
            }
        }
    }
    for(int i=1;i<=n;i++) g[i]=g[i]*g[i-1]%mod;
}
ll solve(int n,int m){
    ll ans=1;
    if(n>m) swap(n,m);
    for(int i=1,pos;i<=n;i=pos+1){
        pos=min(n/(n/i),m/(m/i));
        ans=ans*fpow(g[pos]*fpow(g[i-1],mod-2)%mod,1LL*(n/i)*(m/i))%mod;
    }
    return ans;
}
int main(){
    pre();
    scanf("%d",&T);
    while(T--) scanf("%d%d",&n,&m),printf("%d\n",(int)solve(n,m));
    return 0;
}

 

codevs 5962 [SDOI2017]数字表格

标签:main   while   code   printf   bool   input   ret   media   body   

原文地址:http://www.cnblogs.com/shenben/p/6696501.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!