Problem H
Count the Numbers
Input: standard input
Output: standard output
Time Limit: 2 seconds
You're given three non-negative integers N (0 <= N <= 999), A, B, (0 <= A <= B <= 2000000000). Count the number of integers in the interval [A; B] which contain N as a subsequence.
For example if N = 3, A = 3 and B = 17, there are two integers which contain N as a subsequence: 3 and 13.
Input
The input contains triples of numbers A, B and N. The input ends with "-1 -1 -1". This line should not be processed.
Output
For each triple, output the answer on a new line.
Sample Input Output for Sample Input
3 17 3 | 2
|
Author: Slavi Marinov
Translation and solution: Petko Minkov
思路:我用容斥做的....对N出现的位置进行容斥。 。。然后0 是特判的。
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <map>
#include <stdio.h>
#include <cmath>
#include <cassert>
#include <math.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define LL long long
#define eps 1e-9
#define mp make_pair
using namespace std;
const int maxn = 30;
LL pw[maxn],dp[maxn],g[maxn];
int sum[maxn];
int n;
char S[maxn],T[maxn];
char d[maxn];
int len,nlen;
LL dfs(int cur,bool limit)
{
if (cur == 0) return 1;
if (!limit) return pw[sum[cur]];
if (T[cur] != '?') {
if (limit && T[cur] > d[cur]) return 0;
return dfs(cur-1,limit && T[cur] == d[cur]);
} else {
int tail = limit ? d[cur] : 9;
LL ans = 0;
rep(v,0,tail+1)
ans += dfs(cur-1,limit && v == tail);
return ans;
}
}
LL solve(LL x)
{
if (x < 0) return 0;
sprintf(d+1,"%lld",x);
len = strlen(d+1);
rep(i,1,maxn) d[i] -= '0';
reverse(d+1,d+1+len);
if (n == 0) {
bool ok = false;
LL ans = 0;
rrep(i,len,1) {
for(int v = 0; v < d[i]; ++v) {
if ((i != len && v == 0) || ok) ans += pw[i-1];
else if (i == len && v == 0) ans += g[i-1]+1;
else ans += dp[i-1];
}
if (d[i] == 0) ok = true;
}
if (ok) ++ans;
return ans;
}
int mask = (1<<(len-nlen+1));
LL ans = 0;
rep(s,1,mask) {
rep(j,1,len+1) T[j] = '?';
bool flag = true;
int odd = 0;
for(int j = 0; j < len-nlen+1 && flag; ++j) if (s & (1<<j)) {
for(int k = 0; k < nlen && flag; ++k) {
if (T[k+j+1] == '?') T[k+j+1] = S[k];
else if (T[k+j+1] != S[k]) flag = false;
}
odd ^= 1;
}
reverse(T+1,T+1+len);
if (!flag) continue;
for(int j = 1; j <= len; ++j) {
sum[j] = sum[j-1];
if (T[j] == '?') sum[j]++;
}
if (odd) ans += dfs(len,true);
else ans -= dfs(len,true);
}
return ans;
}
int main()
{
#ifdef ACM
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif // ACM
pw[0] = 1; rep(i,1,maxn) pw[i] = pw[i-1] * 10;
dp[0] = 0;
rep(i,1,maxn) {
dp[i] = pw[i-1] + 9 * dp[i-1];
g[i] = g[i-1] + dp[i-1] * 9;
}
LL A,B;
while (scanf("%lld%lld%d",&A,&B,&n)==3) {
if (n + A + B == -3) break;
sprintf(S,"%d",n);
nlen = strlen(S);
rep(i,0,maxn) S[i] -= '0';
LL ans = 0;
ans += solve(B);
ans -= solve(A-1);
printf("%lld\n",ans);
}
}