1. 程式人生 > 實用技巧 >2020 hdu多校賽 第三場 1006 X Number

2020 hdu多校賽 第三場 1006 X Number

題意:

每次給你 L R d,問L~R中有多少個數 x 滿足 x 各個位上的數 d 為唯一眾數 ,如23323 中的 3,10000中的0,但是2233對於2和3都不算。(L<=1e18,R<=1e18,0<=d<=9)

很顯然,這是一個數位DP,按照數位DP的套路,我們需要計算從高到低前x-1位已經固定,第x位填y時,滿足題意的數有多少。

由於L,R只有1e18,我們不妨列舉d在剩下那幾位中出現的次數,然後通過記憶化搜尋 / 揹包DP 求解。

不過這只是整體思路。在列舉第一位為0時,我們還需要對於前導0特殊處理。總之細節很多,詳情見程式碼。

  1 #include<iostream>
  2
#include<cstdlib> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #define N 25 8 using namespace std; 9 int T; 10 long long L,R,d; 11 int A[N],zz; 12 int cnt[N],D[N]; 13 long long C[N][N]; 14 long long F[11][19][19]; 15
long long dfs(int x,int mx,int sm) 16 { 17 if(x==10) 18 { 19 if(sm==0)return 1; 20 else return 0; 21 } 22 if(x==d) return dfs(x+1,mx,sm); 23 if(F[x][mx][sm]!=-1)return F[x][mx][sm]; 24 long long ans=0; 25 for(int i=0;i<=sm&&i+D[x]<mx;i++)
26 { 27 ans+=1ll*C[sm][i]*dfs(x+1,mx,sm-i); 28 } 29 return F[x][mx][sm]=ans; 30 } 31 long long work(long long x) 32 { 33 zz=0; 34 x++; 35 memset(cnt,0,sizeof(cnt)); 36 long long tmp=x; 37 while(tmp) 38 { 39 zz++; 40 A[zz]=tmp%10; 41 tmp/=10; 42 } 43 for(int i=1;i<=zz/2;i++) 44 { 45 swap(A[i],A[zz-i+1]); 46 } 47 long long ans=0; 48 memset(D,0,sizeof(D)); 49 for(int i=1;i<=zz;i++) 50 { 51 for(int j=0;j<A[i];j++) 52 { 53 if(i==1&&j==0) 54 { 55 if(d!=0) 56 { 57 memset(F,-1,sizeof(F)); 58 for(int k=1;k<zz;k++) 59 { 60 for(int l=1;l<=k;l++) 61 { 62 for(int o=0;o<l;o++) 63 { 64 ans+=C[k-1][o]*C[k-o][l]*dfs(1,l,k-l-o); 65 66 } 67 } 68 } 69 } 70 else 71 { 72 memset(F,-1,sizeof(F)); 73 for(int k=1;k<zz;k++) 74 { 75 for(int l=1;l<k;l++) 76 { 77 ans+=C[k-1][l]*dfs(1,l,k-l); 78 } 79 } 80 } 81 continue; 82 } 83 cnt[j]++; 84 D[j]++; 85 int mx=0; 86 for(int k=0;k<=9;k++) 87 { 88 if(k==d) continue; 89 mx=max(mx,cnt[k]); 90 } 91 if(mx>=cnt[d]) 92 { 93 memset(F,-1,sizeof(F)); 94 for(int k=mx-cnt[d]+1;k<=zz-i;k++) 95 { 96 ans+=C[zz-i][k]*dfs(0,k+cnt[d],zz-i-k); 97 } 98 } 99 else 100 { 101 memset(F,-1,sizeof(F)); 102 for(int k=0;k<=zz-i;k++) 103 { 104 ans+=C[zz-i][k]*dfs(0,k+cnt[d],zz-i-k); 105 // if(x==239) cout<<i<<' '<<j<<' '<<k<<' '<<ans<<' '<<dfs(1,k+cnt[d],zz-i-k)<<endl; 106 } 107 } 108 cnt[j]--; 109 D[j]--; 110 111 } 112 cnt[A[i]]++; 113 D[A[i]]++; 114 } 115 return ans; 116 } 117 int main() 118 { 119 // freopen("test.in","r",stdin); 120 // freopen("1.out","w",stdout); 121 C[0][0]=1; 122 for(int i=1;i<=19;i++) 123 { 124 C[i][0]=1; 125 for(int j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1]; 126 } 127 scanf("%d",&T); 128 while(T--) 129 { 130 scanf("%lld%lld%lld",&L,&R,&d); 131 printf("%lld\n",work(R)-work(L-1)); 132 // cout<<work(R)<<' '<<work(L-1)<<endl; 133 } 134 return 0; 135 } 136 /* 137 1 138 926 949 9 139 140 141 3 142 23123 243353 0 143 23123 243353 5 144 23123 243353 9 145 146 2 147 1 1000 0 148 101 1000 0 149 */
View Code