其他分享
首页 > 其他分享> > CF55D Beautiful numbers

CF55D Beautiful numbers

作者:互联网

题面传送门
首先这种题目肯定数位dp,先反手一个差分。
然后有多组询问考虑先全部处理出来。
但是这个限制不太好处理。
然而我们发现这\(9\)个数字的最大公约数只有\(2520\),那么我们存当前数模\(2520\)的值和所有值的最大公约数即可。然后这个所有值的最大公约数只有\(48\)种,可以优化一下。
然后就是平凡数位dp,时间复杂度\(O(2520\times48\times 19\times 10+T\times 19\times (48+2520))\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 100000
#define M 20000
#define mod 2520
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int T,G[2521],Y[2521],cnt,Lcm[2521][2521];ll po,l,r,tot,pus,now,dp[20][2521][50][10],F[20][2521][50],Ans;
I int lcm(int x,int y){return x*y/__gcd(x,y);} 
I ll solve(ll x){
	re int i,j,k,h;Ans=pus=tot=0;for(po=1e18,i=19;i;i--){//printf("%lld\n",dp[1][3][3][3]);
		for(j=0;j<x/po;j++){
			for(k=1;k<=48;k++){now=Lcm[pus][Y[k]];
				for(h=0;h<mod;h+=now) Ans+=dp[i][(h-tot+mod)%mod][k][j]/*,printf("%lld\n",Ans)*/;
			}
		}tot=(tot+x/po*po)%mod;pus=Lcm[pus][x/po];x%=po;po/=10;
	}return Ans+(!pus||tot%pus==0);
}
int main(){
	freopen("1.in","r",stdin);
	int i,j,h,k;for(i=1;i<=mod;i++)if(mod%i==0)Y[G[i]=++cnt]=i;dp[0][0][1][0]=1;//printf("%d\n",cnt);
	for(i=1;i<=mod;i++) Lcm[i][0]=Lcm[0][i]=i;for(i=1;i<=mod;i++) for(j=1;j<=mod;j++) Lcm[i][j]=lcm(i,j);
	for(po=1,i=0;i<=18;i++){
		for(j=0;j<mod;j++){
			for(k=1;k<=48;k++) for(h=0;h<=9;h++) F[i][j][k]+=dp[i][j][k][h];
		}
		for(j=0;j<mod;j++){
			for(k=1;k<=48;k++){
				for(h=0;h<=9;h++) dp[i+1][(h*po+j)%mod][G[Lcm[Y[k]][h]]][h]+=F[i][j][k];
			}
		}po*=10;
	}//printf("%lld\n",dp[2][15][5][1]);
	scanf("%d",&T);while(T--) scanf("%I64d%I64d",&l,&r),printf("%I64d\n",solve(r)-solve(l-1));
}

标签:Beautiful,2521,2520,int,ll,numbers,CF55D,dp,define
来源: https://www.cnblogs.com/275307894a/p/15028582.html