zoukankan      html  css  js  c++  java
  • 2019-ACM-ICPC-南京区网络赛-E. K Sum-杜教筛+欧拉定理

    2019-ACM-ICPC-南京区网络赛-E. K Sum-杜教筛+欧拉定理


    【Problem Description】

    (f_n(k)=sum_{l_1=1}^nsum_{l_2=1}^ndotssum_{l_k=1}^n gcd(l_1,l_2,dots,l_k))。求(sum_{i=2}^kf_n(i) mod (10^9+7))

    【Solution】

    对于(f_n(k))有:

    [sum_{l_1=1}^nsum_{l_2=1}^ndotssum_{l_k=1}^ngcd(l_1,l_2,dots,l_k)=sum_{d=1}^nsum_{l_1=1}^{frac{n}{d}}sum_{l_2=1}^{frac{n}{d}}dotssum_{l_k=1}^{frac{n}{d}}[gcd(l_1,l_2,dots,l_k)=1]cdot d^2 \=sum_{d=1}^nd^2sum_{t=1}^{n}mu(t)sum_{l_1=1}^{frac{n}{dt}}sum_{l_2=1}^{frac{n}{dt}}dotssum_{l_k=1}^{frac{n}{dt}}=sum_{d=1}^nd^2sum_{t=1}^nmu(t)lfloorfrac{n}{dt} floor^k ]

    (T=dt)得:

    [f_n(k)=sum_{T=1}^{n}sum_{t|T}mu(t)cdotfrac{T^2}{t^2}cdot lfloorfrac{n}{T} floor^k ]

    (sum_{i=2}^kf_n(i))为:

    [sum_{i=2}^kf_n(i)=sum_{i=2}^ksum_{T=1}^nsum_{t|T}mu(t)cdot frac{T^2}{t^2}cdot lfloorfrac{n}{T} floor^k=sum_{T=1}^nsum_{t|T}mu(t)frac{T^2}{t^2}sum_{i=2}^klfloorfrac{n}{T} floor^k \=sum_{T=1}^nsum_{t|T}mu(t)frac{T^2}{t^2}Big(frac{lfloorfrac{n}{T} floor^{k+1}-1}{lfloorfrac{n}{T} floor-1}-lfloorfrac{n}{T} floor-1Big) ]

    因为(kle 10^{10^5}),所以用欧拉定理降幂取模即可。注意特判(lfloor frac{n}{T} floor=1)的情况。
    其中令(g(T)=sum_{t|T}mu(t)cdot frac{T^2}{t^2},Phi(n)=sum_{T=1}^ng(T))。对于(T)小的部分可以通过线性筛求得:

    1. (T)为素数时,(g(T)=T^2-1)
    2. (T)中无平方质因子时(T=p_1cdot p_2dots p_k),因为(g(T))为积形函数,则有(g(T)=g(p_1)cdot g(p_2)dots g(p_k))
    3. (T)中有平方质因子时,有(g(Tcdot p)=g(T)cdot p^2)
      对于(T)大的部分,我们发现(g(T)=mu*id^2(T)),则(g*I(T)=mu*I*id^2(T)=e*id^2(T)=id^2(T)=T^2)
      则有:

    [sum_{T=1}^nT^2=sum_{T=1}^nsum_{d|T}g(d)=sum_{T=1}^nsum_{d|T}sum_{t|d}mu(t)cdot frac{d^2}{t^2}=sum_{T=1}^nsum_{d=1}^{frac{n}{T}}sum_{t|d}mu(t)cdotfrac{d^2}{t^2} \=sum_{T=1}^nPhi(frac{n}{T}),则Phi(n)=frac{ncdot (n+1)cdot (2cdot n+1)}{6}-sum_{T=2}^nPhi(frac{n}{T}) ]


    【Code】

    /*
     * @Author: Simon 
     * @Date: 2019-09-04 15:07:56 
     * @Last Modified by: Simon
     * @Last Modified time: 2019-09-04 16:22:26
     */
    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define maxn 1000005
    typedef long long ll;
    const int mod=1e9+7;
    const int Mod=3e6;
    int prime[maxn],cnt=0,inv6;
    ll phi[maxn],sum[maxn];
    bool vis[maxn]={1,1};
    void Euler(){ //线性筛
        phi[1]=1;
        for(int i=2;i<maxn;i++){
            if(!vis[i]){
                prime[++cnt]=i;
                phi[i]=((i*1LL*i%mod-1)%mod+mod)%mod;
            }
            for(int j=1;j<=cnt&&i*1LL*prime[j]<maxn;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0){
                    phi[i*prime[j]]=phi[i]*1LL*prime[j]%mod*prime[j]%mod;
                    break;
                }
                phi[i*prime[j]]=phi[i]*1LL*phi[prime[j]];
            }
        }
        for(int i=1;i<maxn;i++) sum[i]=(sum[i-1]+phi[i])%mod;
    }
    int fpow(int a,int b,int mod){
        a%=mod; int ans=1;
        while(b){
            if(b&1) ans=1LL*ans*a%mod;
            a=1LL*a*a%mod;
            b>>=1;
        }
        return ans;
    }
    unordered_map<ll,ll>mp;
    int cal(int n,int k1,int k2){ //等比数列求和公式
        if(n==1) return (k2-1)%mod; //特判
        int t1=fpow(n,k1+1,mod)-1LL*n*n%mod,t2=n-1;
        return 1LL*t1*fpow(t2,mod-2,mod)%mod;
    }
    int sum_2(int n){
        n%=mod;
        return 1LL*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    }
    int dfs(int n){ //Phi(n)
        if(n<maxn) return sum[n];
        if(mp[n]) return mp[n];
        int sum=0;
        for(int i=2,j;i<=n;i=j+1){
            j=n/(n/i);
            sum=(sum+(j-i+1)*1LL*dfs(n/i)%mod)%mod;
        }
        sum=(sum_2(n)-sum)%mod;
        mp[n]=sum;
        return sum;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        //freopen("input.in","r",stdin);
        //freopen("output.out","w",stdout);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0);Euler(); inv6=fpow(6,mod-2,mod);
        int T;cin>>T;
        while(T--){
            mp.clear();
            int n;string k;cin>>n>>k;
            int t1=0,t2=0;
            for(int i=0;i<k.size();i++){
                t1=(1LL*t1*10+(k[i]-'0'))%(mod-1);
                t2=(1LL*t2*10+(k[i]-'0'))%mod;
            }
            int ans=0;
            for(int i=1,j;i<=n;i=j+1){
                j=n/(n/i);
                ans=(ans*1LL+(dfs(j)-dfs(i-1))%mod*1LL*cal(n/i,t1,t2)%mod)%mod;
            }
            cout<<(ans+mod)%mod<<endl;
        }
    #ifndef ONLINE_JUDGE
        cout<<endl;system("pause");
    #endif
        return 0;
    }
    
  • 相关阅读:
    clip-path
    box-reflect
    循环内click赋值跳转
    github pages 不能识别下划线开头的文件
    Telerik Reporting
    VS2015项目发布失败且没有错误提示
    kendo grid 过滤器
    kendo 月份选择
    kendo grid过滤
    odata连接现有数据库
  • 原文地址:https://www.cnblogs.com/--Simon/p/11460177.html
Copyright © 2011-2022 走看看