• BZOJ 4815 [Cqoi2017]小Q的表格 ——欧拉函数


    把式子化简一波。

    发现一个比较厉害的性质:每个点只能影响到行列下标$gcd$与它相同的点。

    然后就可以计算$sum_{g<=k}f(g,g)*sum_{i<=k}sum_{j<=k}[gcd(i,j)==g](i/g)*(i/g)$

    然后考虑它的意义,直接发现计算出$i*i*phi(i)$的前缀和就可以下界函数分块计算了。

    这样子还是过不了。考虑修改次数比较少,考虑分块维护,就可以$O(1)$查询了。

    复杂度$msqrt {n}$

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (ll i=j;i<=k;++i)
    #define D(i,j,k) for (ll i=j;i>=k;--i)
    #define ll long long
    #define mp make_pair
     
    const ll md=1000000007;
     
    void Finout()
    {
        freopen("table.in","r",stdin);
        freopen("table.out","w",stdout);
    }
     
    #define maxn 10000001
    int a[maxn],phi[maxn],f[maxn];
    int vis[maxn],pri[maxn],top=0,m,n;
     
    ll Getll()
    {
        ll x=0,f=1; char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
     
    void Shaker()
    {
        phi[1]=1;
        F(i,2,n)
        {
            if (!vis[i]) pri[++top]=i,phi[i]=i-1;
            for (ll j=1;j<=top&&(ll)i*pri[j]<=(ll)n;++j)
            {
                vis[i*pri[j]]=1;
                if (i%pri[j]==0)
                {
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }
                else phi[i*pri[j]]=phi[i]*phi[pri[j]];
            }
        }
        F(i,1,maxn-1) phi[i]=phi[i]*i%md*i%md+phi[i-1],phi[i]%=md;
    }
     
    int sum[50005],pre[maxn];
    int L[50005],R[50005],bel[maxn],T,tot=0;
     
     
    void add(ll x,ll d)
    {
        F(i,x,R[bel[x]])
        {
            pre[i]+=d,pre[i]%=md;
        }
        F(i,bel[x],tot)
        {
            sum[i]+=d,sum[i]%=md;
        }
    }
     
    ll gs(ll x)
    {
        if (x==0) return 0;
        ll ret=0;
        ret=sum[bel[x]-1]+pre[x];
        ret%=md;
        return ret;
    }
     
    ll gcd(ll a,ll b)
    {return b==0?a:gcd(b,a%b);}
     
    ll cal(ll k)
    {
        ll ret=0;
        for (ll i=1,last=0;i<=k;i=last+1)
        {
            last=k/(k/i);
            ret+=phi[k/last]*((gs(last)-gs(i-1))%md);
            ret%=md;
        }
        return (ret+md)%md;
    }
     
    void init()
    {
        T=sqrt(n); //printf("Block Size is %d
    ",T);
        for (ll i=1;i<=n;i+=T)
        {
            L[++tot]=i;
            R[tot]=i+T-1;
        }
        R[tot]=n;
        F(i,1,tot) F(j,L[i],R[i]) bel[j]=i;
    }
     
    int main()
    {
        m=Getll();n=Getll();
        init(); 
        Shaker();
        F(i,1,n) a[i]=((ll)i*i)%md;
        F(i,1,n) (a[i]+=a[i-1])%=md;
        F(i,1,tot) sum[i]=a[R[i]];
        F(i,1,tot)
        {
            pre[L[i]]=(a[L[i]]-a[L[i]-1])%md;
            F(j,L[i]+1,R[i]) pre[j]=(pre[j-1]+a[j]-a[j-1])%md;
        }
        sum[0]=0;
        F(i,1,m)
        {
            ll a,b,k,x;
            a=Getll();b=Getll();x=Getll();k=Getll();
            ll g=gcd(a,b);
            add(g,-gs(g)+gs(g-1));
            ll tmp=x/(a/g)/(b/g);
            tmp%=md;
            add(g,tmp);
            printf("%lld
    ",cal(k));
        }
    }
    

      

  • 相关阅读:
    LeetCode485 最大连续1的个数
    LeetCode167 两数之和 II
    js浮点数类型
    js整数类型
    js布尔类型
    js重复赋值 js数据交换 js调式方法
    JavaScript变量
    数据类型分类
    重复赋值 数据交换 查看程序执行结果
    JS注释 JS变量
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6736871.html
Copyright © 2020-2023  润新知