zoukankan      html  css  js  c++  java
  • [SDOI2017]数字表格

    Description

    对于斐波那契 (F)(T) 次询问,每次给定 (n)(m) ,求

    [prod_{i=1}^n prod_{j=1}^m F_{gcd(i,j)} ]

    Solution

    一开始就很蠢地把 (F_{gcd(i,j)}) 拆成 (gcd(F_{i},F_{j}))。虽然确实有这个结论,但是显然推不下去,而又没有考虑回溯……服了

    其实不拆的话相当好推,就常规套路就行了。令 (c=min(n,m))

    [egin{align} (*)=prod_{d=1}^c F_d^{sum_{i=1}^n sum_{j=1}^m [gcd(i,j)=d]} end{align} ]

    然后立即发现右上角是一个熟悉得不能再熟悉的式子,直接跳过中间步骤,得到

    [egin{align} (1)&=prod_{d=1}^c F_d^{sum_{k=1}^{lfloor frac{n}{d} floor} mu(k)lfloor frac{n}{kd} floorlfloor frac{m}{kd} floor} \ &=prod_{T=1}^c prod_{d|T} F_d^{mu(frac{T}{d})lfloor frac{n}{T} floorlfloor frac{m}{T} floor} \ &=prod_{T=1}^c Big(prod_{d|T} F_d^{mu(frac{T}{d})} Big)^{lfloor frac{n}{T} floorlfloor frac{m}{T} floor} end{align} ]

    随便处理一下,复杂度 (O(Tsqrt nlog n+n log n)),但好像我的跑得很慢?

    #include<stdio.h>
    #define Mod p
    #define ll long long
    #define N 1000007
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    int p=(1e9)+7;
    
    ll qpow(ll x,ll y){
        ll ret=1,cnt=0;
        while(y>=(1ll<<cnt)){
            if(y&(1ll<<cnt)) ret=ret*x%p;
            x=x*x%p,cnt++;
        }
        return ret;
    }
    
    ll f[N][3],g[N];
    int mu[N],P[N],cnt=0;
    bool mk[N];
    
    inline int min(int x,int y){return x<y? x:y;}
    
    int main(){
        f[0][2]=0,f[1][2]=1;
        for(int i=2;i<N;i++) f[i][2]=(f[i-1][2]+f[i-2][2])%Mod;
        for(int i=0;i<N;i++) f[i][0]=qpow(f[i][2],p-2);
        mu[1]=1;
        for(int i=2;i<N;i++){
            if(!mk[i])
                P[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&P[j]*i<N;j++){
                mk[i*P[j]]=1;
                if(i%P[j]) mu[i*P[j]]=-mu[i];
                else break;
            }
        }
        for(int i=0;i<N;i++) g[i]=f[i][1]=1;
        for(int i=1;i<N;i++)
            for(int j=1;j*i<N;j++)
                g[i*j]=g[i*j]*f[i][mu[j]+1]%Mod;
        for(int i=2;i<N;i++) g[i]=g[i]*g[i-1]%Mod;
        int T=read();
        while(T--){
            int n=read(),m=read();
            int rg=min(n,m);
            ll ans=1;
            for(int l=1,r;l<=rg;l=r+1){
                r=min(n/(n/l),m/(m/l));
                ans=ans*qpow(g[r]*qpow(g[l-1],p-2)%p,1ll*(n/l)*(m/l))%p;
            }
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    Vue 事件修饰符 阻止默认事件
    vue created 生命周期
    续集---网络管理常用命令
    网络管理常用命令(6/14) -netstat命令详解
    系统OOM复位定位
    nohup- Shell后台运行
    一个linux命令(6/13):traceroute命令
    一个linux命令(6/12):cat 命令
    linux命令(6/11)--修改文件的用户组chgrp和文件所有者chown
    Linux终端快捷键
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14598495.html
Copyright © 2011-2022 走看看