算法提高 產生數

算法提高 產生數

給出一個整數 n(n<10^30) 和 k 個變換規則(k<=15)。

規則:

一位數可變換成另一個一位數:

規則的右部不能爲零。

例如:n=234。有規則(k=2):

2-> 5

3-> 6

上面的整數 234 經過變換後可能產生出的整數爲(包括原數):

234

534

264

564

共 4 種不同的產生數

問題:

給出一個整數 n 和 k 個規則。

求出:

經過任意次的變換(0次或多次),能產生出多少個不同整數。

僅要求輸出個數。

輸入格式:

n k

x1 y1

x2 y2

… …

xn yn

輸出格式:

一個整數(滿足條件的個數)

輸入樣例:

在這裏給出一組輸入。例如:

234 2
2 5
3 6

輸出樣例:

在這裏給出相應的輸出。例如:

4

方法:

這道題費了不少時間,這道題有好幾個坑,開始我只考慮了X,X位置的數一共有多少個Y,一直不能全部通過,後發現Y也能作爲X,舉個例子:
輸入的是
1234 3
2 3
3 2
3 5

這個並不是有6種,答案應該爲9。2可以變爲3,3可以變爲2、5,但是第二個數變成3後要可以變成2和5,即第二個數有2、3、5三種可能,第三個數有2、3、5三種可能,即答案爲9。這是第一個注意的地方
還有一個需要注意的地方,最後的結果是一個很大的數,我用了long long都不能滿足,最後只能用字符串存這個數。
這個題我是把這個字符串轉換爲字符串數組,滿足條件就在這個字符串後面加入這個字符。以題目爲例
234 2
2 5
3 6

234轉換爲長度爲3的字符串數組
2
3
4

2->5,5不和2這個字符串任何字符重複,插入5,變成
25
3
4

3->6,6不和3這個字符串任何字符重複,插入6,變成
25
36
4

最後結果就是每個字符串長度的乘積。

代碼:

#include<vector>
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
struct num//用結構體存變換的X、Y
{
	char x;
	char y;
};
int main()
{
	string n;
	int x,flag1=1,flag2=1,carry,t;
	vector<int>cnt;//最後的結果
	cnt.push_back(1);
	cin >> n >> x;
	vector<num>arr(x);
	vector<string>nn(n.length());//轉換爲字符串數組
	for (int i = 0; i < n.length(); i++)
	{
		nn[i] += n[i];
	}
	for (int i = 0; i < x; i++)
	{
		cin >> arr[i].x >> arr[i].y;
	}
	for (int m = 0; m < x; m++)//每次循環都要從遍歷所有的X、Y的變換,因爲Y也能作爲X變換
	{
		for (int i = 0; i < x; i++)
		{
			for (int j = 0; j < nn.size(); j++)
			{
				flag1 = 1; flag2 = 1;
				for (int k = 0; k < nn[j].length(); k++)
				{
					if (arr[i].x == nn[j][k])
					{
						flag1 = 0;
					}
					if (arr[i].y == nn[j][k])
					{
						flag2 = 0;
					}
				}
				if (flag1 == 0 && flag2 == 1)//變換的X要在這個字符串的字符中且Y不在字符中
				{
					nn[j] += arr[i].y;
				}
			}
		}
	}
	for (int i = 0; i < nn.size(); i++)//乘法運算
	{
		carry = 0;//進位
		for (int j = cnt.size() - 1; j >= 0; j--)
		{
			t = cnt[j];
			cnt[j] = (cnt[j] * nn[i].length() + carry) % 10;//每一位做乘法後的值
			carry = (t * nn[i].length() + carry) / 10;//進位位的值
		}
		if (carry != 0)
		{
			while (carry >= 1)//!!!!要把進位位分割成每一位存進數組
			{
				cnt.insert(cnt.begin() + 0, carry % 10);//(在數組的第0位插入,即數組最前面)
				carry = carry / 10;
			}
		}
	}
	for (int i = 0; i < cnt.size(); i++)
	{
		cout << cnt[i];
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章