hdu 3943 统计出现了x次4与y次7的数字
统计n以下所有有x次4和y次7的数的个数,然后二分。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 using namespace std; 6 typedef long long LL; 7 int const N = 22; 8 int const M = 22; 9 LL dp[N][N][N]; 10 int bit[N],ln; 11 int x,y; 12 LL getsum1(int t,int limit,int cnt4,int cnt7) 13 { 14 if(cnt4>x||cnt7>y)return 0; 15 if(!t)return (x==cnt4&&y==cnt7); 16 int up=(limit?bit[t]:9); 17 if(!limit&&dp[t][cnt4][cnt7]!=-1)return dp[t][cnt4][cnt7]; 18 LL ans=0; 19 for(int i=0;i<=up;i++) 20 { 21 ans+=getsum1(t-1,limit&&i==up,cnt4+(i==4),cnt7+(i==7)); 22 } 23 if(!limit)dp[t][cnt4][cnt7]=ans; 24 return ans; 25 } 26 LL getsum2(LL n) 27 { 28 for(ln=0;n;bit[++ln]=n%10,n/=10); 29 return getsum1(ln,1,0,0); 30 } 31 int main() 32 { 33 LL P,Q; 34 int T,t=0,n; 35 scanf("%d",&T); 36 while(T--) 37 { 38 memset(dp,-1,sizeof(dp)); 39 scanf("%I64d %I64d",&P,&Q); 40 scanf("%d %d",&x,&y); 41 LL l,r,mid,k,ans; 42 scanf("%d",&n); 43 printf("Case #%d:\n",++t); 44 LL sign=getsum2(P); 45 LL up=getsum2(Q)-sign; 46 for(int i=0;i<n;i++) 47 { 48 scanf("%I64d",&k); 49 if(k>up){printf("Nya!\n");continue;} 50 l=P+1,r=Q; 51 while(l<r) 52 { 53 mid=(l+r)>>1; 54 LL cnt=getsum2(mid); 55 cnt-sign>=k?(r=mid):(l=mid+1); 56 } 57 printf("%I64d\n",l); 58 } 59 } 60 return 0; 61 }