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;
}


你可能感兴趣的:(UVa 12377 - Number Coding)