原题直通车:HDU 3652 B-number
题意: 求1~n中有多少数含有"13"且是13的倍数.
代码:
递归式:
//904 KB 46 ms G++ 856 B
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int digit[12], dp[12][13][3], n;
int next(int l, int i) {
if(l==0) {
if(i==1) return 1;
else return 0;
}
if(l==1) {
if(i==3) return 2;
if(i==1) return 1;
return 0;
}
return 2;
}
int dfs(int pos, int y, int l, bool limit) {
if(!pos) return (l==2&&y==0);
if(!limit&&dp[pos][y][l]!=-1) return dp[pos][y][l];
int ret=0, len=(limit?digit[pos]:9);
for(int i=0; i<=len; ++i)
ret+=dfs(pos-1, (y*10+i)%13, next(l, i), limit&&i==len);
if(!limit) dp[pos][y][l]=ret;
return ret;
}
int work(int n) {
int len=0;
while(n) digit[++len]=n%10, n/=10;
memset(dp, -1, sizeof(dp));
return dfs(len, 0, 0, true);
}
int main() {
while(~scanf("%d",&n)) printf("%d\n", work(n));
return 0;
}
非递归式:
// 312 KB 15 ms G++ 1307 B
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
LL dp[12][10][13][2], f[12];
int digit[12];
int digit_dp() {
memset(dp, 0LL, sizeof(dp));
dp[0][0][0][0]=f[0]=1LL;
for(int i=1; i<12; ++i) f[i]=f[i-1]*10LL;
for(int i=0; i<11; ++i)
for(int j=0; j<10; ++j) // 第i位
for(int k=0; k<13; ++k){
for(int p=0; p<10; ++p) //第i+1位
dp[i+1][p][(p*f[i]+k)%13][1]+=dp[i][j][k][1];
for(int p=0; p<10; ++p)
if(j==3&&p==1) dp[i+1][p][(p*f[i]+k)%13][1]+=dp[i][j][k][0];
else dp[i+1][p][(p*f[i]+k)%13][0]+=dp[i][j][k][0];
}
}
int work(int x) {
int len=0, y=0, ret=0, q=0;
memset(digit, -1, sizeof(digit));
while(x) digit[++len]=x%10, x/=10;
for(int i=len; i>=1; --i) {
for(int j=0; j<digit[i]; ++j) {
ret+=dp[i][j][(13-y)%13][1];
if(q) ret+=dp[i][j][(13-y)%13][0];
else if(digit[i+1]==1&&j==3) ret+=dp[i][j][(13-y)%13][0];
}
if(digit[i+1]==1&&digit[i]==3) q=1;
y=(y+digit[i]*f[i-1])%13;
}
return ret;
}
int main() {
digit_dp();
int n;
while(~scanf("%d",&n)) printf("%d\n", work(n+1));
return 0;
}