zoukankan      html  css  js  c++  java
  • 【bzoj】P4407于神之怒加强版(莫比乌斯反演)

      题目链接

      套路一般的枚举$gcd(i,j)=w$。设$min(n,m)=top$,则有

      $sumlimits_{i=1}^{n}sumlimits_{j=1}{m}gcd(i,j)$

      $=sumlimits_{w=1}^{top}w^{k}sumlimits_{w|i}^{n}sumlimits_{w|j,(i,j)=w}^{m}1$

      我们设$f(w)=sumlimits_{w|i}^{n}sumlimits_{w|j,(i,j)=w}^{m}1$

      $F(w)=sumlimits_{w|i}^{n}sumlimits_{w|j}^{m}1$

      则有$F(w)=sumlimits_{w|d}f(d)$

      然后就根据莫比乌斯反演公式

      $f(w)=sumlimits_{w|d}mu(frac{d}{w})F(w)$

      然后容易想到$F(w)=frac{n}{w}frac{m}{w}$

      然后就有了原式

      $=sumlimits_{w=1}^{top}w^{k}sumlimits_{d=1}^{frac{top}{w}}mu(d)frac{n}{wd}frac{m}{wd}$

      然后……Timelimitexceed,我就看题解了。

      枚举t=wd。然后数论分块乱搞。

      讲道理我如果抗住题解的诱惑自己推的话还是可以推出来的qwq。

      

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #define maxn 6000010
    #define mod 1000000007
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int miu[maxn];
    bool s[maxn];
    int prime[1000010],tot;
    long long mul[maxn];
    long long sum[maxn];
    
    long long Pow(long long n,int i,long long p){
        long long ret=1;
        while(i){
            if(i&1)    ret=(ret*n)%p;
            n=(n*n)%p;
            i>>=1;
        }
        return ret;
    }
    
    int main(){
        int T=read(),L=read();
        miu[1]=mul[1]=sum[1]=1;
        for(int i=2;i<maxn;++i){
            if(!s[i]){
                prime[++tot]=i;
                mul[tot]=Pow(i,L,mod);
                sum[i]=mul[tot]-1;
            }
            for(int j=1;j<=tot&&1LL*i*prime[j]<=maxn;++j){
                s[i*prime[j]]=1;
                if(i%prime[j])    sum[i*prime[j]]=(1ll*sum[i]*sum[prime[j]])%mod;
                else{
                    sum[i*prime[j]]=(1ll*sum[i]*mul[j])%mod;
                    break;
                }
            }
        }
        for(int i=2;i<maxn;++i){
            sum[i]+=sum[i-1];
            sum[i]%=mod;
        }
        while(T--){
            int n=read(),m=read();
            int top=min(n,m);
            int x=1; long long ans=0;
            if(n>m)    swap(n,m);
            while(x<=top){
                int y=min(n/(n/x),m/(m/x));
                ans+=1ll*(n/x)*(m/x)%mod*(sum[y]-sum[x-1])%mod;
                ans%=mod;
                x=y+1;
            }
            printf("%lld
    ",(ans+mod)%mod);
        }
        return 0;
    }
    
    /*
    1 2
    3 3
    */
  • 相关阅读:
    《卓有成效的管理者》读后感
    小课堂week13 Clean Code Part2
    小课堂Week12 Clean Code Part1
    小课堂Week11 会说话的代码
    小课堂Week10 例外处理设计的逆袭Part3
    Spark菜鸟学习营Day6 分布式代码运行调试
    UML(一) 类图及类间关系
    分布式事务(一)两阶段提交及JTA
    Java线程间通信方式剖析——Java进阶(四)
    Java进阶(三)多线程开发关键技术
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8268272.html
Copyright © 2011-2022 走看看