NKOJ 4040 (CQOI 2017) 小Q的表格(莫比乌斯反演+分块+递推+线性筛/欧拉函数+分块+线性筛)
来源:互联网 发布:拇指特效软件 编辑:程序博客网 时间:2024/05/22 03:02
P4040小Q 的表格
问题描述
题目给出了一个有规律的表格,因此我们先随便修改一个数找一下所有被修改的数之间有没有什么规律,很容易发现好像被修改的数的行号和列号的gcd是一样的,于是我们考虑证明,实际上我们的修改过程和辗转相减的过程是一样的,因此很容易得证。
接着我们来考虑gcd一样的这些格子的数有什么特点,容易发现他们的倍数关系是固定的,等于行号列号乘积之商,所以我们用A[d]表示(d,d)这个格子的值,列出求和式
接下来就有两种做法了。
做法一:
上面的式子看起来很眼熟,于是我们将他变形
于是莫比乌斯反演一下,
现在,我们希望把A[d]后面的一坨解决掉,于是,我们令
现在我们发现,如果能预处理出
不妨令右边这一坨为
因此我们有
然后
最后还需要注意,分块时我们需要
因此我们需要用到分块前缀和这种黑科技,它可以实现
附上代码
#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#define ll long long#define N 4444444using namespace std;const ll mod=1000000007LL;ll A[N],S[N],Q[N],sn,ssn,n,m;ll pri[N],G[N],F[N],tot;bool mark[N];ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}void Pretreat(){ ll i,j; for(i=1;i<=n;i++) { A[i]=i*i%mod; S[i]=(S[i-1]+A[i])%mod; } F[1]=1;G[1]=1; for(i=2;i<=n;i++) { if(!mark[i])pri[++tot]=i,F[i]=i*i%mod*(i-1)%mod; for(j=1;j<=tot&&pri[j]*i<=n;j++) if(i%pri[j])mark[i*pri[j]]=1,F[i*pri[j]]=F[i]*F[pri[j]]%mod; else {mark[i*pri[j]]=1;F[i*pri[j]]=F[i]*(pri[j]*pri[j]%mod)%mod*pri[j]%mod;} G[i]=(G[i-1]+F[i])%mod; }}void MD(ll x,ll d){ ll i,l=(x-1)/sn+1,r=l*sn; for(i=x;i<=r&&i<=n;i++)S[i]=(S[i]+d)%mod; for(i=l+1;i<=ssn;i++)Q[i]=(Q[i]+d)%mod;}ll GS(ll x){ ll l=(x-1)/sn+1; if(x==0)return 0; return (S[x]+Q[l])%mod;}int main(){ ll i,j,k,t,a,b,x,y,ans; scanf("%lld%lld",&m,&n); Pretreat();sn=sqrt(n);ssn=(n-1)/sn+1; for(i=1;i<=m;i++) { scanf("%lld%lld%lld%lld",&a,&b,&x,&k); y=gcd(a,b); x=x/(a*b/y/y)%mod; MD(y,x-A[y]); A[y]=x;ans=0; for(j=1;j<=k;j=t+1) { t=k/(k/j); ans=(ans+G[k/j]*(GS(t)-GS(j-1))%mod)%mod; } printf("%lld\n",(ans+mod)%mod); }}
做法二:
做法二非常的厉害,我们先回顾一下做法一中
然后,厉害的来了,根据欧拉函数的性质,我们有
注意到
于是,后面一坨显然是积性的,之后同样分块处理即可。
关于这个公式的证明,注意到如果a和n互质,那么n-a和n也一定互质,因为假设p同时整除n和n-a,那么他一定整除a,矛盾。
以下代码引用自F.F.Chopin,同时不得不说,做法二比做法一跑得要快,因为预处理取模较少,更快。
#include<stdio.h>#include<cmath>#define LL long longconst int MAXN=4000005;const LL mod=1000000007;using namespace std;LL m,n,prime[MAXN>>3],phi[MAXN],tot,g[MAXN],w[MAXN],f[MAXN],tg[MAXN];bool ntpr[MAXN];LL a,b,x,k,d,nn;LL gcd(LL a,LL b){ if(!b)return a; return gcd(b,a%b);}void getphi(int n){ phi[1]=g[1]=f[1]=w[1]=1; for(LL i=2; i<=n; i++) { if(!ntpr[i]) prime[++tot]=i,phi[i]=i-1; for(int j=1; j<=tot&&i*prime[j]<=n; j++) { ntpr[i*prime[j]]=1; if(!(i%prime[j])) { phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*(prime[j]-1); } f[i]=i*i%mod; g[i]=(g[i-1]+f[i]*phi[i]%mod)%mod; w[i]=(w[i-1]+f[i])%mod; }}void calc(LL k){ LL ans=0,i,ls; for(i=1; i<=k; i=ls+1) { ls=k/(k/i); ans=((w[ls]-w[i-1]+tg[(ls+nn-1)/nn]-tg[(i+nn-2)/nn])*g[k/i]%mod+ans)%mod; } printf("%lld\n",(ans+mod)%mod);}int main(){ scanf("%lld%lld",&m,&n); getphi(n); nn=sqrt(n); LL c,v; while(m--) { scanf("%lld%lld%lld%lld",&a,&b,&x,&k); d=gcd(a,b); c=f[d],f[d]=x/(a/d)/(b/d)%mod; for(int i=d; i<=(nn-1+d)/nn*nn; i++) w[i]=(w[i]+f[d]-c)%mod; for(int i=(d+nn-1)/nn+1; i<=(n+nn-1)/nn; i++) tg[i]=(tg[i]+f[d]-c)%mod; calc(k); }}
阅读全文
0 0
- NKOJ 4040 (CQOI 2017) 小Q的表格(莫比乌斯反演+分块+递推+线性筛/欧拉函数+分块+线性筛)
- bzoj 4815: [Cqoi2017]小Q的表格 分块+莫比乌斯反演
- [分块 莫比乌斯反演] BZOJ 4815 [Cqoi2017]小Q的表格
- 【bzoj2820】YY的GCD 线性筛法+莫比乌斯反演+数论分块
- hdu 4746 Mophues (莫比乌斯反演 + 分块+线性筛)
- 线性筛求莫比乌斯反演函数+分块+前缀和
- 【bzoj2301】[HAOI2011]Problem b 莫比乌斯反演+线性筛法+数论分块
- 【bzoj3529】[Sdoi2014]数表 线性筛法+树状数组+莫比乌斯反演+数论分块
- 【bzoj3994】[SDOI2015]约数个数和 线性筛法+莫比乌斯反演+数论分块
- HDOJ 1695 GCD(容斥+欧拉函数&&莫比乌斯反演+分块)
- [BZOJ4804][积性函数][线性筛][莫比乌斯反演]欧拉心算
- SPOJ PGCD(mobius反演+分块+线性筛)
- bzoj 2301 -莫比乌斯函数反演+分块优化
- NKOJ 3800 分解质因数(欧拉函数+线性筛)
- NKOJ 3249(CQOI 2015) 选数(莫比乌斯反演,杜教筛)
- NKOJ 4038(CQOI 2017) 小Q的棋盘(贪心)
- 积性函数、线性筛、莫比乌斯反演和一堆乱七八糟的题目
- 欧拉线性筛&欧拉函数&莫比乌斯函数
- 如何确认同一网段
- CodeChef ISCC2017 HISTOSIM
- hdu4607—Park Visit(树的直径)
- Codis源码解析——proxy添加到集群
- 深入浅出Tensorflow(五):循环神经网络简介
- NKOJ 4040 (CQOI 2017) 小Q的表格(莫比乌斯反演+分块+递推+线性筛/欧拉函数+分块+线性筛)
- “玲珑杯”ACM比赛 Round #19 E.Expected value of the expression【Dp】
- 老生常谈之SQL Server (行转列,列转行)
- 环境变量的配置
- golang 实现一种环形队列,及周期任务
- 打造 高性能,轻量级的 webform框架---js直接调后台
- 设计模式基本原则
- 结合Unity浅谈设计模式-单例
- MyBatis中Like语句使用总结