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)$查询了。

复杂度$m\sqrt {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\n",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\n",cal(k));
    }
}

  

posted @ 2017-04-20 08:49  SfailSth  阅读(192)  评论(0编辑  收藏  举报