[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\n",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\n",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\n",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\n",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\n",lnum,mx); 59 printf("Case #%d:\n",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 \n",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\n",ans[i]); 72 } 73 return 0; 74 }
话说网上有些题解遇到极限数据会炸>_<。。