• 洛咕 P3700 [CQOI2017]小Q的表格


    洛咕 P3700 [CQOI2017]小Q的表格


    神仙题orz

    首先推一下给的两个式子中的第二个

    (bcdot F(a,a+b)=(a+b)cdot F(a,b))

    先简单的想,(F(a,a+b))(F(a,b))会相互影响

    可以换一种角度想,(F(a,b-a))(F(a,b))会相互影响((b>a))

    那么可以从(F(x,y))一路推下去

    (F(x,y)=F(x,y-x)=F(x,y-2x)=cdots=F(x,ymod x))

    (注意这里的( ext{mod})结果是0的话就没有办法再减了)

    这时横坐标比纵坐标大了,利用题目给的式子1,swap横纵坐标

    (F(x,y)=F(x,ymod x)=F(ymod x,x)=F(ymod x,xmod(ymod x))=cdots)

    总结一下,如果继续这样推下去,当横、纵坐标相等时会就不能再减了

    刚才是怎么推的呢,就是当x,y不等的时候每次都把x对y取模然后交换x,y

    是不是很熟悉,就是求gcd的过程

    那么可以推出来,(gcd(x,y))相等的会相互影响

    具体影响多少是显然的,(F(x,y)=F(gcd(x,y),gcd(x,y)) imes frac{xy}{gcd(x,y)^2})

    所以只要维护(F(i,i))的值就行了,下面设(F(i,i)=F(i))

    现在要算(sum_{i=1}^nsum_{j=1}^nF(i,j))

    (ans=sum_{i=1}^nsum_{j=1}^nF(gcd(i,j)))

    考虑枚举(gcd(i,j))

    (ans=sum_{k=1}^nF(k)sum_{i=1}^nsum_{j=1}^nfrac{ij}{k^2}[gcd(i,j)=k])

    (ans=sum_{k=1}^nF(k)sum_{i=1}^{n/k}sum_{j=1}^{n/k}ij[gcd(i,j)=1])

    (g(n)=sum_{i=1}^{n}sum_{j=1}^{n}ij[gcd(i,j)=1])(ans=sum_{k=1}^nF(k)g(n/k))

    可以只求一半,(g(n)=2sum_{i=1}^{n}sum_{j=1}^{i}ij[gcd(i,j)=1]-sum_{i=1}^{n}i^2[gcd(i,i)=1])

    右边那一块是显然的

    (g(n)=2sum_{i=1}^{n}sum_{j=1}^{i}ij[gcd(i,j)=1]-1)

    (h(n)=sum_{i=1}^{n}in[gcd(i,n)=1])(g(n)=2sum_{i=1}^{n}h(i)-1)

    怎么求(h)呢,显然可行的(i)(varphi(n))种,如果(gcd(i,n)=1),那么(gcd(n-i,n)=1)

    所以(i)(n-i)可以配对,加起来是(n),一共(varphi(n)/2)对,(h(n)=frac{varphi(n) imes n^2}{2}),注意特判(h(n)=1),因为不能配对

    然后求出了(h)就可以求出(g)(F)每次只会修改一个。要求的(ans=sum_{k=1}^nF(k)g(n/k))显然(n/k)只有根号种取值,数论分块即可,(F)树状数组前缀和

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    #define int ll
    #define mod 1000000007
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int g[4000010],h[4000010];
    int pri[4000010],pr,phi[4000010];
    bool yes[4000010];
    int n,m,f[4000010];
    il vd update(int x,int p){while(x<=n)f[x]=(f[x]+p)%mod,x+=x&-x;}
    il int query(int x){int ret=0;while(x)ret=(ret+f[x])%mod,x-=x&-x;return ret;}
    signed main(){
        m=gi(),n=gi();
        int x,y,k,t,G;
        for(int i=1;i<=n;++i)update(i,1ll*i*i%mod);
        phi[1]=1;
        for(int i=2;i<=n;++i){
            if(!yes[i])phi[i]=i-1,pri[++pr]=i;
            for(int j=1;j<=pr&&i*pri[j]<=n;++j){
                yes[i*pri[j]]=1;
                if(i%pri[j]==0){
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }
                phi[i*pri[j]]=phi[i]*(pri[j]-1);
            }
        }
        for(int i=1;i<=n;++i)h[i]=1ll*phi[i]*i%mod*i%mod;
        g[1]=1;
        for(int i=2;i<=n;++i)g[i]=(g[i-1]+h[i])%mod;
        while(m--){
            x=gi(),y=gi();G=std::__gcd(x,y);
            t=(gi()/(x/G)/(y/G))%mod;
            update(G,(0ll+t-query(G)+query(G-1)+mod)%mod);
            k=gi();
            int ans=0;
            for(int i=1;i<=k;++i){
                int j=k/(k/i);
                ans=(ans+1ll*(query(j)-query(i-1)+mod)*g[k/i])%mod;
                i=j;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    2
    1
    java10
    java8
    java9
    java7
    java6
    java5
    java4
    java3
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10075424.html
Copyright © 2020-2023  润新知