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 }
原文地址:https://www.cnblogs.com/nuoyan2010/p/3069664.html