【BZOJ4815】小Q的表格（CQOI2017）-数论+分块

$f\left(a,b\right)=f\left(b,a\right)$
$b\cdot f\left(a,a+b\right)=\left(a+b\right)\cdot f\left(a,b\right)$

$f\left(a,b\right)=\frac{b}{b\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}a}\cdot \frac{a}{a\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}\left(b\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}a\right)}\cdot f\left(b\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}a,a\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}\left(b\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}a\right)\right)$

$ans=\sum _{i=1}^{n}\sum _{j=1}^{n}f\left(i,j\right)$

$ans=\sum _{d=1}^{n}f\left(d,d\right)\sum _{i=1}^{⌊\frac{n}{d}⌋}\sum _{j=1}^{⌊\frac{n}{d}⌋}\left[gcd\left(i,j\right)=1\right]ij$
$g\left(n\right)=\sum _{i=1}^{n}\sum _{j=1}^{n}\left[gcd\left(i,j\right)=1\right]ij$，显然式子就变成了一个数论分块的形式，那么现在有两个问题要处理：

$\sum _{i=1}^{n}\left[gcd\left(i,n\right)=1\right]i=\frac{\phi \left(n\right)}{2}n$

$g\left(n\right)=g\left(n-1\right)+{n}^{2}\phi \left(n\right)$

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
int m;
ll n,blocksiz,prime[2000010],g[4000010];
ll val[4000010],sum[4000010],blocksum[10010];
bool vis[4000010]={0};

void calc_g()
{
prime[0]=0;
g[0]=0,g[1]=1;
for(ll i=2;i<=n;i++)
{
if (!vis[i])
{
prime[++prime[0]]=i;
g[i]=i*i%mod*(i-1)%mod;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if (i%prime[j]==0)
{
g[i*prime[j]]=g[i]*prime[j]%mod*prime[j]%mod*prime[j]%mod;
break;
}
g[i*prime[j]]=g[i]*prime[j]%mod*prime[j]%mod*(prime[j]-1)%mod;
}
}
for(ll i=1;i<=n;i++)
g[i]=(g[i]+g[i-1])%mod;
}

void init()
{
scanf("%d%lld",&m,&n);

blocksiz=sqrt(n);
blocksum[0]=0;
for(ll i=1,nowblock=0;i<=n;i++)
{
val[i]=i*i%mod;
if (i%blocksiz) sum[i]=(sum[i-1]+val[i])%mod;
else sum[i]=val[i];
if (i%blocksiz==blocksiz-1)
blocksum[(i+1)/blocksiz]=(blocksum[i/blocksiz]+sum[i])%mod;
}
calc_g();
}

ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}

void modify(ll pos,ll x)
{
val[pos]=x;
for(int i=pos;;i++)
{
if (i%blocksiz==blocksiz-1) break;
}
for(int i=pos/blocksiz+1;i<=n/blocksiz+1;i++)
}

ll query(ll l,ll r)
{
l--;
ll ans=0;
if (l>0) ans=ans-blocksum[l/blocksiz]-sum[l];
ans=ans+blocksum[r/blocksiz]+sum[r];
ans=(ans%mod+mod)%mod;
return ans;
}

void work()
{
ll a,b,k,x;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld%lld",&a,&b,&x,&k);

ll d=gcd(a,b);
x/=a/d*b/d;
modify(d,x);

ll ans=0;
for(ll i=k;i>=1;i=k/(k/i+1))
{
ll l=k/(k/i+1)+1,r=i;
ans=(ans+query(l,r)*g[k/i])%mod;
}
printf("%lld\n",ans);
}
}

int main()
{
init();
work();

return 0;
}
posted @ 2018-05-25 11:23  Maxwei_wzj  阅读(121)  评论(0编辑  收藏  举报