1. 程式人生 > >Codeforces 55d-----狀壓dp and math

Codeforces 55d-----狀壓dp and math

一點 tail amp pro 定義 printf 一段 for 鏈接

先貼一下題目鏈接: https://vjudge.net/problem/CodeForces-55D

題意大致如下: 給t次詢問, 每次詢問給出一段區間【l,r】 要你求出這段區間中的beautiful number

漂亮數定義如下: 一個數如果為漂亮數 是它可以 被它的非零數位 整除!

然後貼一下別人的題解::::::::::::https://blog.csdn.net/Rain722/article/details/54709913

首先可以確認一點 1: 如果一個數可以被多個數整除, ((那麽最重要的一點是先找出這個數的lcm))!

2:可以得出1到9這9個數的lcm是2520 (暴力算一下就可以)

3:顯然在數位上的操作一般都是數位dp

4:可以確定一點, <<pos(也就是數位肯定是第一維狀態)>>,那怎麽唯一確定它的狀態了 我們想既然找整除的數那麽最終是找 余數/lcm==0,那麽狀態就可以劃分成 數位,,,余數,,,,lcm,,,,,,, 然後余數的範圍可以限制到2520,lcm由於限制它只有50個數:::::::::

那麽就可以推出了!

技術分享圖片
 1 #include<bits/stdc++.h>
 2
using namespace std; 3 typedef long long LL; 4 const int mod=2520; 5 int t; 6 LL l,r; 7 LL dp[25][50][2550]; // 數位 lcm 余數 8 int Hash[2550]; //把lcm hash出來 9 int bit[25]; 10 11 LL gcd(LL a,LL b){ 12 if(b==0) return a; 13 else return gcd(b,a%b); 14 } 15 16 void init(){ 17 int cnt=0;
18 for(int i=1;i<=mod;i++) 19 if(mod%i==0) 20 Hash[i]=cnt++; 21 } 22 23 LL dfs(int pos,int have,int lcm,int lim){ 24 if(pos<=0) return have%lcm==0; 25 if(!lim&&dp[pos][Hash[lcm]][have]!=-1) return dp[pos][Hash[lcm]][have]; 26 int num=lim?bit[pos]:9; 27 LL ans=0; 28 for(int i=0;i<=num;i++){ 29 ans+=dfs(pos-1,(have*10+i)%mod,i==0?lcm:lcm*i/gcd(lcm,i),lim&&i==num); 30 } 31 if(!lim) dp[pos][Hash[lcm]][have]=ans; 32 return ans; 33 } 34 LL solve(LL m){ 35 int len=0; 36 while(m){ 37 bit[++len]=m%10;m/=10; 38 } 39 return dfs(len,0,1,1); 40 } 41 42 int main(){ 43 init(); 44 scanf("%d",&t); 45 memset(dp,-1,sizeof(dp)); //dp數組初始化 46 while(t--){ 47 scanf("%lld%lld",&l,&r); 48 printf("%lld\n",solve(r)-solve(l-1)); 49 } 50 return 0; 51 }
View Code

一個不錯的鏈接:::::https://www.cnblogs.com/vongang/p/3141273.html

Codeforces 55d-----狀壓dp and math