给定一个整数,求在不包含某个小串的系列中该整数的位置
http://acm.hust.edu.cn/thx/problem.php?cid=1025&pid=0
此数为不含4、13的子串,求其现在的位置。注意输出:windows系统用I64d,linux用lld,教训
个 十 百 千 ……
开始个位取4,左边有1方法,右边n/10+(n%10>4?1:0),再十位,左边个位可以选择9种方法,乘以右边的方法。再考虑13,在十位 右边n/10+(n%10*10+个位>13?1:0),左边为1。之后从百位开始,其低位数应该*9-再低2位(临的低2位用13填了)
#include <iostream>
using namespace std;
long long a[14],b[14],res;
void cal(long long n,int i,int k)
{
if(n==0)
return;
res+=a[i]*(n/10);
if(n%10>4)
res+=a[i];
res+=b[i]*(n/10);
if((n%10)*10+k>13)
res+=b[i];
cal(n/10,i+1,n%10);
}
int main()
{
int i;
long long k,h,t;
a[0]=1;
b[0]=0;
for(i=1;i<14;i++){
a[i]=a[i-1]*9-b[i-1];
b[i]=a[i-1];
}
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld",&k,&h);
res=0;
cal(k,0,0);
printf("%lld\n",(k-res)*h);
}
return 0;
}
标程答案:
#include <stdio.h>
#include <string.h>
#define ok(a,b) (b!=4 && !(a==1 && b==3))
long long dp[10][13], T, h;
char k[100];
int main(){
for (int F=0; F<10; F++) dp[F][0] = 1;
for (int L=1; L<13; L++)
for (int F=0; F<10; F++) if (F!=4)
for (int D=0; D<10; D++) if (ok(F,D))
dp[F][L] += dp[D][L-1];
scanf("%lld",&T);
while (T--){
scanf("%s %lld",k,&h);
long long floors = 0;
for (int i=0, L=strlen(k); i<L; i++)
for (int F=0; F<k[i]-'0'; F++)
if (ok(i==0?0:k[i-1]-'0',F))
floors += dp[F][L-i-1];
printf("%lld\n",floors * h);
}
}