【莫比乌斯反演+数位DP】2017 计蒜之道 复赛 A.阿里云秘钥池
2017-12-11 06:56
393 查看
题面在这里
首先容斥一下,变为求[1,n]有多少数在P进制下相邻位互质
然后就可以DP了:fi,j表示前i位,最高位上是j的方案数
fi,j=∑k=1P−1 [gcd(j,k)=1]fi−1,k=∑k=1P−1fi−1,k∑d|j,d|kμ(d)=∑d|jμ(d)∑dt≤P−1fi−1,dt
然后可以发现,已知fi−1的情况下,∑dt≤P−1fi−1,dt是可以O(P⋅lnP)求得的
然后通过枚举d,也是可以实现O(P⋅lnP)的转移
所以总复杂度为O(logRP⋅P⋅lnP)=O(PlogR2)
示例程序:
首先容斥一下,变为求[1,n]有多少数在P进制下相邻位互质
然后就可以DP了:fi,j表示前i位,最高位上是j的方案数
fi,j=∑k=1P−1 [gcd(j,k)=1]fi−1,k=∑k=1P−1fi−1,k∑d|j,d|kμ(d)=∑d|jμ(d)∑dt≤P−1fi−1,dt
然后可以发现,已知fi−1的情况下,∑dt≤P−1fi−1,dt是可以O(P⋅lnP)求得的
然后通过枚举d,也是可以实现O(P⋅lnP)的转移
所以总复杂度为O(logRP⋅P⋅lnP)=O(PlogR2)
示例程序:
#include<cstdio> #include<cstring> #define cl(x,y) memset(x,y,sizeof(x)) typedef long long ll; const int maxn=100005,N=maxn-5; int tst,P; ll L,R,f[70][maxn]; int p[maxn],mu[maxn]; bool vis[maxn]; void prepare(){ mu[1]=1; for (int i=2;i<=N;i++){ if (!vis[i]) p[++p[0]]=i,mu[i]=-1; for (int j=1;j<=p[0]&&i*p[j]<=N;j++){ vis[i*p[j]]=1; if (i%p[j]==0) {mu[i*p[j]]=0;break;} else mu[i*p[j]]=-mu[i]; } } } int a[70]; int gcd(int x,int y){ return y==0?x:gcd(y,x%y); } ll dfs(int i,int j,bool b){ if (i==1) return 1; if (!b&&f[i][j]) return f[i][j]; int Max=0;if (b) Max=a[i-1];else Max=P-1; ll res=0; for (int k=1;k<=Max;k++) if (gcd(j,k)==1) res+=dfs(i-1,k,b&&(Max==k)); return res; } ll calc(ll x){ cl(a,0);ll N=x; do a[++a[0]]=N%P,N/=P; while(N); ll res=0; for (int i=1;i<a[0];i++) for (int j=1;j<P;j++) res+=dfs(i,j,0); for (int j=1;j<=a[a[0]];j++) res+=dfs(a[0],j,j==a[a[0]]); return res; } void DP(){ cl(a,0);ll N=R; do a[++a[0]]=N%P,N/=P; while(N); for (int i=1;i<=a[0];i++) for (int j=0;j<P;j++) f[i][j]=0; for (int j=1;j<P;j++) f[1][j]=1; for (int i=2;i<=a[0];i++) for (int d=1;d<P;d++){ ll g=0; for (int k=d;k<P;k+=d) g+=f[i-1][k]; for (int j=d;j<P;j+=d) f[i][j]+=mu[d]*g; } } int main(){ prepare(); scanf("%d",&tst); while (tst--){ scanf("%lld%lld%d",&L,&R,&P); DP(); printf("%lld\n",calc(R)-calc(L-1)); } return 0; }
相关文章推荐
- [数位DP 莫比乌斯反演] 2017 计蒜之道 复赛 A. 阿里云秘钥池
- 【计蒜客】「2017 计蒜之道 复赛」A.阿里云秘钥池 数位DP+莫比乌斯函数
- 【数位DP+莫比乌斯函数】2017计蒜之道复赛A[阿里云秘钥池]题解
- [莫比乌斯反演+数位DP]计蒜客 阿里云秘钥池
- 2017百度之星复赛:1006. Valley Numer(数位DP)
- [数位DP Lucas定理] 2017 计蒜之道 复赛 E. 商汤智能机器人
- HDU 6148 && 2017 百度之星复赛 1005 Valley Numer(数位dp)
- [lucas+数位DP] 2017 计蒜之道 复赛 E. 商汤智能机器人
- 2017 百度之星 复赛 Valley Numer(数位dp)
- 2017百度之星复赛 hdu 6148 Valley Numer (数位dp)
- [反演] 2017 计蒜之道 复赛 A. 阿里云秘钥池
- 2017中国大学生程序设计竞赛 - 网络选拔赛 && HDU 6156 Palindrome Function 【数位DP】
- 计蒜之道-2017复赛-腾讯消消乐(状压DP)
- 百度之星复赛--Valley Numer----数位dp
- [数位DP] ZROI 2017 提高3 T1 树状数组
- HDU6146(2017百度之星程序设计大赛 - 复赛)[Pokémon GO]--DP
- 计蒜客 2017 复赛 腾讯消消乐 (状压dp)
- 2017广东工业大学程序设计竞赛决赛 Problem G: 等凹数字(回文+数位dp)
- JZOJ5379. 【NOIP2017提高A组模拟9.21】Victor爱数字 数位DP
- 计蒜之道 2017 程序设计大赛 - 计蒜客 复赛 F 腾讯消消乐 状态压缩dp、枚举+剪枝