zoukankan      html  css  js  c++  java
  • LOJ #6539 奇妙数论题

    不想咕太久..就随便找个题更一下

    LOJ#6539


    题意

    求题面里那个式子


    题解

    有一个常用的小式子

    $$sum_{x|a,x|b}varphi(x)=gcd(a,b)$$

    用这个式子直接对题面的式子进行化简

    $$
    egin{aligned}
    &sum_{i=1}^nsum_{j=1}^n(a_i,a_j)·(i,j)\
    &=sum_{i=1}^nsum_{j=1}^n(sum_{x|i,x|j}varphi(x))(a_i,a_j)\
    &=sum_{x=1}^nvarphi(x)sum_{x|i}sum_{x|j}(a_i,a_j)
    end{aligned}
    $$

    枚举x,相当于求一个大小为$ frac{n}{x}$的集合内两两$ gcd$的和

    再用一次最上面的式子优化

    $$
    egin{aligned}
    &sum_{i=1}^nsum_{j=1}^ngcd(a_i,a_j)\
    &=sum_{d=1}^nvarphi(d)(sum_{i=1}^n[d|a_i])^2
    end{aligned}
    $$

    预处理每个数的约数,每次暴力计算

    复杂度是对的..跑的飞快...


    代码

    小范围暴力抢了rk1

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define rt register int
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0;char zf=1;char ch=getchar();
        while(ch!='-'&&!isdigit(ch))ch=getchar();
        if(ch=='-')zf=-1,ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    int k,m,n,x,y,z,cnt,ans;
    #define N 100000
    bool pri[N+10];int ss[N+10],phi[N+10];
    void init(){
        phi[1]=1;
        for(rt i=2;i<=N;i++){
            if(!pri[i]) ss[++cnt]=i,phi[i]=i-1;
            for(rt j=1;j<=cnt&&i*ss[j]<=N;j++){
                phi[i*ss[j]]=phi[i]*phi[ss[j]];
                pri[i*ss[j]]=1;
                if(i%ss[j]==0){
                    phi[i*ss[j]]=phi[i]*ss[j];
                    break;
                }
            }
        }
    }
    int a[100010],sum[100010];
    vector<int>ys[100010];
    ll calc2(int x){
        ll ret=0;
        for(rt i=x;i<=n;i+=x)sum[a[i]]++;
        for(rt i=1;i<=n;i++){
            int now=0;
            for(rt j=i;j<=n;j+=i)now+=sum[j];
            ret+=1ll*phi[i]*now*now;
        }
        for(rt i=x;i<=n;i+=x)sum[a[i]]=0;
        return ret;
    }
    ll calc(int x){
        ll ret=0;
        for(rt i=x;i<=n;i+=x){
            for(auto j:ys[a[i]]){
                ret+=(sum[j]*2+1)*phi[j];
                sum[j]++;
            }
        }
        for(rt i=x;i<=n;i+=x){
            for(auto j:ys[a[i]])sum[j]=0;
        }    
        return ret;
    }
    int main(){
        init();n=read();
        for(rt i=1;i<=n;i++)a[i]=read();
        for(rt i=1;i<=n;i++)
        for(rt j=i;j<=n;j+=i)ys[j].push_back(i);
        ll ans=0;
        for(rt x=1;x<=n;x++){
            if(x<=10)ans+=1ll*phi[x]*calc2(x);else 
            ans+=1ll*phi[x]*calc(x);
        }
        cout<<ans%1000000007;
        return 0;
    }
  • 相关阅读:
    获取图片的大小(宽高):BytesIO
    python中url解析 or url的base64编码
    [extjs5学习笔记]第三十七节 Extjs6预览版都有神马新东西
    【翻译】Ext JS 6早期访问版本发布
    【翻译】Ext JS 6有什么新东西?
    【Java二十周年】Delphi转行java的一些小感触
    Cursor类取出数据
    通过服务修改widgetUI
    安卓笔记--Style的继承
    [ExtJS5学习笔记]第三十六节 报表组件mzPivotGrid
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10650992.html
Copyright © 2011-2022 走看看