【ブルーブリッジカップ】ポイント付き。フルアレンジ+賢い判断

元のタイトル

以前のテスト問題のスコアを含むテスト問題 http://lx.lanqiao.cn/problem.page?gpid=T26

問題の説明

100は、混合数として表すことができます:100 = 3 +69258/714。

100 = 82 +3546/197として表すこともできます。

機能に注意してください。混合番号では、番号1〜9が別々に1回だけ表示されます(0は含まれません)。

このような混合数の100の11の表現があります。

入力フォーマット

標準入力から正の整数Nを読み取ります(N <1000 * 1000)

出力フォーマット

プログラムは、1〜9桁の数字を出力して、繰り返しや省略なしに、混合数で表されるすべての数字を形成します。

注:すべての表現を出力する必要はありません。表現の数を数えるだけです。

サンプル入力1

100

サンプル出力1

11

サンプル入力2

105

サンプル出力2

6

分析

1.完全な配置を実現する

9つの数字は繰り返されないので、私は自然にすべての配置を考えました。9!= 362880。この完全な数は1秒以内に完了することができます。ここでは、再帰的+マーキングによって完全な配置を直接実装します。もちろん、以下のリファレンスブログも理解しにくい実装を提供しており、効率は少し高いようです。

2.質問の意味を満たす方程式かどうかを巧みに判断します

すべての順列のシーケンスを取得した後、このシーケンスに対応する方程式が質問の意味を満たしていると判断するにはどうすればよいですか?

シーケンスには9桁あり、num []配列を使用してインストールします。num[0] 〜num [8]。

(1)a <= nなので、a <= nの桁数

(2)yizhi(1)の条件に従ってaを列挙します。また、シーケンスnum [8]の最後のビットはcの最後のビットでもあるためです。したがって、bの最後の桁は次のように推測できます。bLast=((na)* num [8])%10;

(3)bの最後の桁がわかっている場合は、aの後のbLastを探すことができます(b> = cの桁であるため、開始位置の方が正確です)。存在する場合は、(b%c == 0 && n == a + b / c)が質問の意味を満たしているかどうかが判断されます。

参照ブログ:http//lx.lanqiao.cn/problem.page?gpid = T26

効果

コード 

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

int n;
int len = 0;

int num[15]; // 存放9个数字的全排列
int vis[15]; // 标志数字在之前是否已使用
int ans = 0;

// [start, end)
int getNum(int start, int end) {
	int t = 0;
	// 1 2 3
	for(int i = start; i < end; i++) {
		t = 10*t + num[i];
	}
		
	return t;
}

void print() {
	for(int i = 0; i < 9; i++)
		printf("%d ", num[i]);
	printf("\n");
}

void dfs(int k) { // 0
	if (k >= 9) {
//		print();
		
		// 得到一个全排列
		for(int i = 1; i <= len; i++) { // a的长度必定在[1, len]
			int a = getNum(0, i);
			// n = a + b / c   =>  b = (n - a) * c
			int bLast = ((n - a)*num[8]) % 10; // b的最后一位
			
			for(int j = (i-1)+ceil((9-i)/2); j < 8; j++) {
				
				if(num[j] == bLast) {
					int b = getNum(i, j+1);
					int c = getNum(j+1, 9);
					
					if(b%c == 0 && n == a + b/c) {
						ans++;	
					}
					
					break;  // 可以提高效率 
				}
			} 
		}

		return;
	}

	for(int i=1; i<=9; i++)
		if(vis[i]==0) { // 数字未被使用
			num[k]=i;  // 填入
			vis[i]=1; // 标记已被使用

			dfs(k+1); // 搜索下一个位置

			num[k]=0;
			vis[i]=0; // 解除标记
		}


}

int main() {
	scanf("%d", &n);

	// 计算n有多少位,a的位数不可能多比n的位数
	int t=n;
	while(t!=0) {
		len++;
		t /= 10;
	}
	
	dfs(0);
	printf("%d\n", ans);

	return 0;
}

 

おすすめ

転載: blog.csdn.net/qq_43290318/article/details/108659028