[hdu3943]K-th Nya Number

  挺正常的一道模板题。

  f[i][j][k]表示i位的数,有j个4,k个7的方案数。

  具体实现的话...我写了发二分答案。。需要注意的是二分时应该是mid=L+(R-L)/2。。不然分分钟爆longlong(unsigned long long党自行退散

  其实也可以从左端点开始慢慢爬。。。但总觉得比较蛋疼所以没敢写

  由网上题解可得,其实还可以确定答案的位数后,从高位往低位一个一个试= =...复杂度会比二分答案的少个log

  需要注意一下对0的特判。。

  对于从左端点爬到根再爬到右端点的奇怪姿势一直不敢碰。。药丸的节奏啊= =。。GDOI应该不会出这么sxbk的东西吧(手动立flag?

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 struct poi{
 8     ll k;int id;
 9 }q[233];ll ans[233];
10 ll f[20][21][21],ten[20];bool u[20][21][21];
11 int i,j,x,y,X,Y,num;
12 ll l,r,tmp;
13 int s[23],len;
14 
15 bool cmp(poi a,poi b){return a.k<b.k;}
16 inline ll get(ll x){
17     for(tmp=x,len=0;tmp;tmp/=10)s[++len]=tmp%10;
18     if(!x)s[len=1]=0;
19     ll ans=0;register int i,j;int sx=X,sy=Y;
20     if(X+Y>len)return 0;
21     for(i=sx+sy;i<len;i++)
22         for(j=1;j<=9;j++)
23             if((sx||j!=4)&&(sy||j!=7))ans+=f[i-1][sx-(j==4)][sy-(j==7)];
24 //    printf("     %lld
",ans);
25     for(i=1;i<s[len];i++)
26         if((sx||i!=4)&&(sy||i!=7))ans+=f[len-1][sx-(i==4)][sy-(i==7)];
27     sx-=s[len]==4,sy-=s[len]==7;
28     for(i=len-1;i&&sx>=0&&sy>=0;i--){
29         for(j=0;j<s[i];j++)
30             if((sx||j!=4)&&(sy||j!=7))ans+=f[i-1][sx-(j==4)][sy-(j==7)];
31         sx-=s[i]==4,sy-=s[i]==7;
32     }
33     if(!sx&&!sy&&x)ans++;
34 //    printf("     %lld
",ans);
35     return ans+(!X&&!Y);
36 }
37 int main(){
38     f[1][1][0]=f[1][0][1]=1;f[1][0][0]=8;f[0][0][0]=1;
39     for(i=ten[0]=1;i<=18;i++)ten[i]=ten[i-1]*10;
40     for(i=2;i<=19;i++){
41         for(x=1;x<=i;x++)for(y=i-x;y;y--)
42             f[i][x][y]=x<=y?(f[i-1][x][y]*8+f[i-1][x-1][y]+f[i-1][x][y-1]):f[i][y][x]
43         ;//    ,printf("  %d %d %d   %lld
",i,x,y,f[i][x][y]);
44         for(x=1;x<=i;x++)f[i][x][0]=f[i][0][x]=f[i-1][x-1][0]+f[i-1][x][0]*8;
45         f[i][0][0]=f[i-1][0][0]<<3;
46     //    if(i<=3)
47     //    for(x=0;x<=i;x++)for(y=0;y<=i-x;y++)printf("  %d %d %d  %lld
",i,x,y,f[i][x][y]);
48     }
49     int T,TT;scanf("%d",&TT);
50     for(T=1;T<=TT;T++){
51         scanf("%lld%lld%d%d",&l,&r,&X,&Y);scanf("%d",&num);
52         for(i=1;i<=num;i++)scanf("%lld",&q[i].k),q[i].id=i;
53         
54         sort(q+1,q+1+num,cmp);
55         ans[0]=l;
56         ll lnum=get(l),mx=get(r)-lnum;
57         
58     //    printf("    lnum:%lld   mx:%lld
",lnum,mx);
59         printf("Case #%d:
",T);
60         for(i=1;i<=num;i++){
61             ll L=ans[q[i-1].id],R=r,mid;
62             if(q[i].k==q[i-1].k){ans[q[i].id]=L;continue;}
63             if(q[i].k>mx){ans[q[i].id]=-1;continue;}
64             while(L<R){
65                 mid=L+((R-L)>>1);//printf("   %lld %lld  
",L,R);
66                 if(get(mid)>=q[i].k+lnum)R=mid;else L=mid+1;
67             }//puts("");
68             ans[q[i].id]=L;
69         }
70         for(i=1;i<=num;i++)
71             if(ans[i]==-1)puts("Nya!");else printf("%lld
",ans[i]);
72     }
73     return 0;
74 }
View Code

  话说网上有些题解遇到极限数据会炸>_<。。

原文地址:https://www.cnblogs.com/czllgzmzl/p/5223916.html