1. 程式人生 > >[排列組合]不少於n個數字組成的數的統計

[排列組合]不少於n個數字組成的數的統計

http://acm.buaa.edu.cn/problem/364/

n位數 首位確定

從0-9選出2個 填到n-1個格子方法

a = 9 * (2 ^ (n - 1) - 2) 種

從0-9選出1個 填到n-1個格子方法

b = 10 種

因此10 ^ n 到 (10 ^ (n + 1) - 1)

共有 9 * (a + b) 種

以下SB邏輯 我已經不記得怎麼想的了......

#include <iostream>
#include <cstring>
using namespace std;
int f[] = {99,351,927,2151,4671,9783,20079};
char a[10];

int getr(char arr[], int l, int u, int p, int q)
{
	if(l > u) return 0;
	int tot(0);
	int c = (int)(arr[l] - '0');
	if(p == q)
	{
		if(l == u) return c + 1;
		tot = c << (u - l);
		if(c > p)
			tot += (8 << (u - l)) - 8;
		if(c > p) q = c;
		else p = c;
	}
	else
	{
		if(c < p) return 0;
		if(l == u)
		{
			if(c >= q) return 2;
			else return 1;
		}
		if(c > p && c < q) return 1 << (u - l);
		if(c > q) return 1 << (u - l + 1);
		if(c == q) tot = 1 << (u - l);
	}
	return tot + getr(arr, l + 1, u, p, q);
}

int main()
{
	while(cin >> a)
	{
		int n = strlen(a);
		switch(n)
		{
		case 1:
			cout << a[0] << endl;
			break;
		case 2:
			cout << a[0] << a[1] << endl;
			break;
		case 10:
			cout << 40744 << endl;
			break;
		default:
			int tot = f[n - 3];
			int a1 = (int)(a[0] - '0');
			tot += (10 + 9 * ((1 << (n - 1)) - 2)) * (a1 - 1);
			tot += getr(a, 1, n - 1, a1, a1);
			cout << tot << endl;
			break;
		}
	}
}