【数位DP+莫比乌斯函数】2017计蒜之道复赛A[阿里云秘钥池]题解

来源:互联网 发布:淘宝月销量怎么变少了 编辑:程序博客网 时间:2024/06/06 10:01

题目概述

[L,R] 中有多少数在 P 进制下任意相邻位互质。

解题报告

肯定是数位DP,把转移方程表示出来:

f[i][j]=k=1P1f[i1][k]×[(j,k)=1]=k=1P1f[i1][k]×e[(j,k)]=k=1P1f[i1][k]d|j,d|kμ(d)=d|jμ(d)t=1P1df[i1][dt]

所以当已知 f[i1] 的时候,就可以用两次类似埃式筛的方法求出 f[i] 。效率 Plog2PlogPR=Plog2R

示例程序

#include<cstdio>#include<cstring>using namespace std;typedef long long LL;const int maxl=60,maxp=1e5;int te,P,mu[maxp+5],p[maxp+5];bool pri[maxp+5];int a[maxl+5];LL L,R,f[maxl+5][maxp+5];void Make(){    pri[1]=true;mu[1]=1;    for (int i=2;i<=maxp;i++)    {        if (!pri[i]) p[++p[0]]=i,mu[i]=-1;        for (int j=1,t;j<=p[0]&&(t=i*p[j])<=maxp;j++)        {            pri[t]=true;mu[t]=-mu[i];            if (!(i%p[j])) {mu[t]=0;break;}        }    }}int gcd(int a,int b) {if (!b) return a;return gcd(b,a%b);}LL Dfs(int i,int j,bool fl){    if (i==1) return 1;if (!fl&&f[i][j]) return f[i][j];    int MAX=0;if (fl) MAX=a[i-1]; else MAX=P-1;LL ans=0;    for (int k=1;k<=MAX;k++) if (gcd(j,k)==1) ans+=Dfs(i-1,k,fl&&k==MAX);    if (!fl) f[i][j]=ans;return ans;}inline LL Solve(LL x){    a[0]=0;do a[++a[0]]=x%P,x/=P; while (x);LL ans=0;    for (int i=1;i<a[0];i++)    for (int j=1;j<P;j++)        ans+=Dfs(i,j,false);    for (int j=1;j<=a[a[0]];j++) ans+=Dfs(a[0],j,j==a[a[0]]);    return ans;}int main(){    freopen("program.in","r",stdin);    freopen("program.out","w",stdout);    for (Make(),scanf("%d",&te);te;te--)    {        scanf("%lld%lld%d",&L,&R,&P);        LL x=R;a[0]=0;do a[++a[0]]=x%P,x/=P; while (x);        for (int i=0;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 sum=0;for (int t=d;t<P;t+=d) sum+=f[i-1][t];            for (int t=d;t<P;t+=d) f[i][t]+=sum*mu[d];        }        printf("%lld\n",Solve(R)-Solve(L-1));    }    return 0;}
阅读全文
0 0
原创粉丝点击