类型:数学
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4151
思路:先求出从1位到len - 1位的总数,然后逐位求解
例如:3235,首先求出长度为1, 2, 3的符合条件的总数,然后计算首位小于3的数据,再计算首位为3时第二位小于2的数据,然后计算前两位为32第三位小于3的数据量。
这时第三位为3在前面已经出现过,所以323-的所有数据不合法,即可直接退出
!!!数据1003 答案738
// hdoj 4151 The Special Number
// wa wa wa wa ac 0MS 220K
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define CLR(a,b) memset(a,b,sizeof(a))
char ch[10];
int dp[10] = {1, 9, 9*9, 9*9*8, 9*9*8*7, 9*9*8*7*6, 9*9*8*7*6*5, 9*9*8*7*6*5*4, 9*9*8*7*6*5*4*3};
int tmp_sum, sum;
bool vis[10];
int main() {
int i, j, tt;
while(scanf("%d", &tt) != EOF) {
CLR(vis, false);
if(tt <= 1) {
printf("0\n");
continue;
}
itoa(tt, ch, 10);
int len = strlen(ch);
sum = 0;
FORE(i, 1, len - 1)
sum += dp[i];
i = -1;
while(1) {
++i;
if(i >= len)
break;
tmp_sum = (int)(ch[i] - '0');
if(i == 0)
--tmp_sum;
int tmp_cnt =0;
FOR(j, 0, (int)(ch[i] - '0'))
if(vis[j])
tmp_cnt++;
tmp_sum -= tmp_cnt;
int tmp = 10 - i, tmp0 = 1;
FOR(j, i + 1, len) {
tmp--;
tmp0 *= tmp;
}
tmp_sum *= tmp0;
sum += tmp_sum;
if(vis[(int)(ch[i] - '0')])
break;
vis[(int)(ch[i] - '0')] = true;
}
printf("%d\n", sum);
}
return 0;
}