[莫比乌斯反演+数位DP]计蒜客 阿里云秘钥池
2017-12-10 20:41
274 查看
f[i][j]=∑k=1P−1f[i−1][k]∗e(gcd(j,k))
f[i][j]=∑k=1P−1f[i−1][k]∑d|j,d|kμ(d)
f[i][j]=∑d|jμ(d)∗∑k=1⌊p−1d⌋f[i−1][kd]
然后就数位DP一下
#include<cstdio> #include<algorithm> using namespace std; #define ll long long #define N 100013 int T,P,mu ,prim ,c[70]; char p ; ll l,r,sum,f[70] ; void pre(void){ ll t;mu[1]=1; for(int i=2;i<=N;++i){ if(!p[i])prim[++prim[0]]=i,mu[i]=-1; for(int j=1;j<=prim[0]&&(t=1ll*i*prim[j])<=100000;++j){ p[t]=1; if(i%prim[j]==0){ mu[t]=0;break; } mu[t]=-mu[i]; } } return ; } int gcd(int a,int b){ return a%b==0?b:gcd(b,a%b); } ll calc(ll x){ ll sum=0,a=x; int tot=0; while(a)c[++tot]=a%P,a/=P; for(int i=tot;i;--i){ for(int j=1;j<c[i];++j) if(i==tot||(gcd(j,c[i+1])==1)) sum+=f[i][j]; if(c[i]==0)break; if(i!=tot&&gcd(c[i],c[i+1])!=1)break; } for(int i=tot-1;i;--i) for(int j=1;j<P;++j) sum+=f[i][j]; return sum; } int main(void){ register int i,j,k,len; ll x; pre(),scanf("%d",&T); while(T--){ scanf("%lld%lld%d",&l,&r,&P); x=r+1,len=0;while(x)x/=P,++len; for(i=1;i<P;++i)f[1][i]=1; for(i=2;i<=len;++i){ for(j=1;j<P;++j)f[i][j]=0; for(j=1;j<P;++j){ sum=0; for(k=j;k<P;k+=j) sum+=f[i-1][k]; for(k=j;k<P;k+=j) f[i][k]+=mu[j]*sum; } } printf("%lld\n",calc(r+1)-calc(l)); } return 0; }
相关文章推荐
- 【莫比乌斯反演+数位DP】2017 计蒜之道 复赛 A.阿里云秘钥池
- 【计蒜客】「2017 计蒜之道 复赛」A.阿里云秘钥池 数位DP+莫比乌斯函数
- [数位DP 莫比乌斯反演] 2017 计蒜之道 复赛 A. 阿里云秘钥池
- 【数位DP+莫比乌斯函数】2017计蒜之道复赛A[阿里云秘钥池]题解
- HDU - 4352 XHXJ's LIS(数位DP+状态压缩)
- 数位DP 刷水
- hihocoder 1259 (数位DP)
- 【POJ】2346 - Lucky tickets(数位dp)
- hdu 2089 不要62 (数位DP)
- BZOJ 1026 数位dp
- HDU 2089 不要62(数位DP)
- HDU 4734 F(x) (数位DP)
- 【AC自动机+数位DP】【zoj 3494】BCD Code
- 数位DP入门 HDOJ2089学模板
- POJ 3252 Round Numbers 数位dp
- Codeforces 809C [数位DP]
- 【AC自动机+数位DP】SDOI2014 数数
- poj 3252 Round Numbers 数位dp
- poj 3252 Round Numbers(数位dp)
- CodeForces 215E Periodical Numbers 数位DP