UVa 12377 - Number Coding
题目:一个数能够用一种素数元素的个数表示的形式,43560=23×32×51×112表示成41223;
第一个数是素因子的种类,第二个是每一个素因子的个数递增排列。给你一个这样的形式的串,
问原来的数可能有几种情况。
分析:数论,计数原理,组合数学。
对于每一个串,第一个数字一定是素因子的种类数。
首先,利用搜索找到全部剩余串的可能组合形式。
然后。求出每种情况下的组合数。加和就可以。
说明:注意一个新的数字不能以0開始。
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> using namespace std; int p[11],f[11]; char buf[22]; long long value(int s, int t) { long long V = 0LL; for (int i = s ; i <= t ; ++ i) { V *= 10LL; V += buf[i]-'0'; } return V; } long long save[11]; long long temp[11]; long long dfs(int s, int l, int d, int n) { long long sum = 0LL; if (d == n && s == l) { sum = 0LL+p[n]; //去掉同样元素的内部排列 int count = 1; for (int i = 1 ; i < d ; ++ i) { if (save[i] == save[i-1]) count ++; else { sum /= f[count]; count = 1; } } sum /= f[count]; } for (int i = s ; i < l ; ++ i) { save[d] = value(s, i); if ((!d || save[d] >= save[d-1]) && buf[i+1] != '0') { temp[d] = save[d]; sum += dfs(i+1, l, d+1, n); save[d] = temp[d]; } } return sum; } int main() { p[0] = 1; f[0] = 1; for (int i = 1 ; i < 10 ; ++ i) { p[i] = p[i-1]*(10-i); f[i] = f[i-1]*i; } int n,l,d; while (~scanf("%d",&n)) for (int i = 1 ; i <= n ; ++ i) { scanf("%s",buf); l = strlen(buf); cout << dfs(1, l, 0, buf[0]-'0') << endl; } return 0; }