洛谷 P1037产生数题解--zhengjun

题目描述

给出一个整数 \(n\)\(n \lt 10^{30}\))和 \(k\) 个变换规则(\(k \le 15\))。

规则:

一位数可变换成另一个一位数。
规则的右部不能为零。
例如:\(n=234\)。有规则(\(k=2\)):

  • \(2\)->\(5\)
  • \(3\)->\(6\)

上面的整数 234234 经过变换后可能产生出的整数为(包括原数):

  • \(234\)
  • \(534\)
  • \(264\)
  • \(564\)

\(4\) 种不同的产生数。

现在给出一个整数 \(n\)\(k\) 个规则。求出经过任意次的变换(\(0\)次或多次),能产生出多少个不同整数。

仅要求输出个数。

输入格式

第一行两个整数 \(n,k\)

接下来 \(n\) 行,每行两个整数 \(x_i,y_i\)

输出格式

输出能生成的数字个数。

输入输出样例

输入 #1 复制
234 2
2 5
3 6
输出 #1 复制
4

思路

一道弗洛伊德的最入门的题目
就是算出每一个数字可以转换成多少种不同的数字,然后把\(n\)的每一位上的数可以变换的数字乘起来就可以了,注意\(n\)要用字符串处理,答案要高精

代码(前面的都是高精度模板)

#include<string>
#include<iostream>
#include<iosfwd>
#include<cmath>
#include<cstring>
#include<stdlib.h>
#include<stdio.h>
#include<cstring>
#define maxl 10000
using namespace std;
/******************模板******************/
class bign{
	public:
		int len,s[maxl];
		bign();
		bign(const char*);
		bign(int);
		bool sign;
		string toStr() const;
		friend istream& operator>>(istream &,bign &);
		friend ostream& operator<<(ostream &,bign &);
		bign operator=(const char*);
		bign operator=(int);
		bign operator=(const string);
		bool operator>(const bign &) const;
		bool operator>=(const bign &) const;
		bool operator<(const bign &) const;
		bool operator<=(const bign &) const;
		bool operator==(const bign &) const;
		bool operator!=(const bign &) const;
		bign operator+(const bign &) const;
		bign operator++();
		bign operator++(int);
		bign operator+=(const bign&);
		bign operator-(const bign &) const;
		bign operator--();
		bign operator--(int);
		bign operator-=(const bign&);
		bign operator*(const bign &)const;
		bign operator*(const int num)const;
		bign operator*=(const bign&);
		bign operator/(const bign&)const;
		bign operator/=(const bign&);
		bign operator%(const bign&)const;
		bign factorial()const;
		bign sqrt(bign)const;
		bign pow(const bign&)const;
		void clean();
		~bign();
};
#define max(a,b)((a)>(b)?(a):(b))
#define min(a,b)((a)<(b)?(a):(b))
bign::bign(){
	memset(s,0,sizeof(s));
	len=1;
	sign=1;
}
bign::bign(const char *num){
	*this=num;
}

bign::bign(int num){
	*this=num;
}

string bign::toStr() const {
	string res;
	res="";
	for(int i=0;i<len;i++)
		res=(char)(s[i] + '0')+res;
	if(res== "")
		res="0";
	if(!sign&&res!="0")
		res="-"+res;
	return res;
}

istream &operator>>(istream &in, bign &num){
	string str;
	in>>str;
	num=str;
	return in;
}

ostream &operator<<(ostream &out, bign &num){
	out<<num.toStr();
	return out;
}

bign bign::operator=(const char *num){
	memset(s, 0, sizeof(s));
	char a[maxl]="";
	if(num[0]!='-')
		strcpy(a,num);
	else
		for(int i=1;i<strlen(num);i++)
			a[i-1]=num[i];
	sign=!(num[0]=='-');
	len=strlen(a);
	for(int i=0;i<strlen(a);i++)
		s[i]=a[len-i-1]-48;
	return *this;
}
bign bign::operator=(int num){
	if(num<0)
		sign=0,num=-num;
	else
		sign=1;
	char temp[maxl];
	sprintf(temp,"%d",num);
	*this=temp;
	return *this;
}

bign bign::operator=(const string num){
	const char *tmp;
	tmp=num.c_str();
	*this=tmp;
	return *this;
}

bool bign::operator<(const bign &num) const {
	if(sign^num.sign)
		return num.sign;
	if(len!=num.len)
		return len<num.len;
	for (int i=len-1;i>=0;i--)
		if (s[i]!=num.s[i])
			return sign?(s[i]<num.s[i]):(!(s[i]<num.s[i]));
	return !sign;
}
bool bign::operator>(const bign&num)const {
	return num<*this;
}
bool bign::operator<=(const bign&num)const {
	return !(*this>num);
}
bool bign::operator>=(const bign&num)const {
	return !(*this<num);
}
bool bign::operator!=(const bign&num)const {
	return *this>num||*this<num;
}
bool bign::operator==(const bign&num)const {
	return !(num!=*this);
}
bign bign::operator+(const bign &num) const {
	if(sign^num.sign){
		bign tmp=sign?num:*this;
		tmp.sign=1;
		return sign?*this-tmp:num-tmp;
	}
	bign result;
	result.len=0;
	int temp=0;
	for (int i=0;temp||i<(max(len, num.len));i++){
		int t=s[i]+num.s[i]+temp;
		result.s[result.len++]=t%10;
		temp=t/10;
	}
	result.sign=sign;
	return result;
}
bign bign::operator++(){
	*this=*this+1;
	return *this;
}
bign bign::operator++(int){
	bign old=*this;
	++(*this);
	return old;
}
bign bign::operator+=(const bign &num){
	*this=*this+num;
	return *this;
}

bign bign::operator-(const bign &num)const{
	bign b=num,a=*this;
	if(!num.sign&&!sign){
		b.sign=1;
		a.sign=1;
		return b-a;
	}
	if(!b.sign){
		b.sign=1;
		return a+b;
	}
	if(!a.sign){
		a.sign=1;
		b=bign(0)-(a+b);
		return b;
	}
	if(a<b){
		bign c=(b-a);
		c.sign=false;
		return c;
	}
	bign result;
	result.len=0;
	for (int i=0,g=0;i<a.len;i++){
		int x=a.s[i]-g;
		if(i<b.len)x-=b.s[i];
		if(x>=0)g=0;
		else{
			g=1;
			x+=10;
		}
		result.s[result.len++]=x;
	}
	result.clean();
	return result;
}

bign bign::operator * (const bign &num)const {
	bign result;
	result.len=len+num.len;
	for(int i=0;i<len;i++)
		for(int j=0;j<num.len;j++)
			result.s[i+j]+=s[i]*num.s[j];
	for(int i=0;i<result.len;i++){
		result.s[i+1]+=result.s[i]/10;
		result.s[i]%=10;
	}
	result.clean();
	result.sign=!(sign^num.sign);
	return result;
}

bign bign::operator*(const int num)const {
	bign x=num;
	bign z=*this;
	return x*z;
}
bign bign::operator*=(const bign&num){
	*this=*this*num;
	return *this;
}
bign bign::operator /(const bign&num)const{
	bign ans;
	ans.len=len-num.len+1;
	if (ans.len<0){
		ans.len=1;
		return ans;
	}
	bign divisor=*this,divid=num;
	divisor.sign=divid.sign=1;
	int k=ans.len-1;
	int j=len-1;
	while(k>=0){
		while(divisor.s[j]==0)j--;
		if (k > j) k = j;
		char z[maxl];
		memset(z,0,sizeof(z));
		for (int i=j;i>=k;i--)
			z[j-i]=divisor.s[i]+'0';
		bign dividend=z;
		if (dividend<divid){
			k--;
			continue;
		}
		int key=0;
		while(divid*key<=dividend)key++;
		key--;
		ans.s[k]=key;
		bign temp=divid*key;
		for(int i=0;i<k;i++)
			temp=temp*10;
		divisor=divisor-temp;
		k--;
	}
	ans.clean();
	ans.sign=!(sign^num.sign);
	return ans;
}
bign bign::operator/=(const bign&num){
	*this=*this/num;
	return *this;
}
bign bign::operator%(const bign& num)const {
	bign a=*this,b=num;
	a.sign=b.sign=1;
	bign result,temp=a/b*b;
	result=a-temp;
	result.sign=sign;
	return result;
}
bign bign::pow(const bign& num)const {
	bign result=1;
	for(bign i=0;i<num;i++)
		result=result*(*this);
	return result;
}
bign bign::factorial()const {
	bign result=1;
	for(bign i=1;i<=*this;i++)
		result*=i;
	return result;
}
void bign::clean(){
	if(len==0)len++;
	while(len>1&&s[len-1]=='\0')
		len--;
}
bign bign::sqrt(bign a)const{
	if(a<0)return -1;
	if(a<=1)return *this;
	bign l=0,r=a,mid;
	while(r-l>1){
		mid=(l+r)/2;
		if(mid*mid>a)
			r=mid;
		else
			l=mid;
	}
	return l;
}
bign::~bign(){}
/******************模板******************/
bign ans;
string n;
int k;
int x[16],y[16];
int f[10][10];
int t[10];
int main(){
	cin>>n>>k;
	for(int i=1;i<=k;i++)cin>>x[i]>>y[i],f[x[i]][y[i]]=1;
	for(int k=1;k<10;k++)
	    for(int i=0;i<10;i++)
	        for(int j=0;j<10;j++)
	            if(f[i][k]&&f[k][j])
	                f[i][j]=1;
	for(int i=0;i<10;i++){
		f[i][i]=1;
		for(int j=0;j<10;j++)
		    t[i]+=f[i][j];
	}
	ans=1;
	for(int i=0;i<n.length();i++)
		ans*=t[n[i]-'0'];
	cout<<ans;
	return 0;
}

模板可以自己拿去用

谢谢--zhengjun

posted @ 2022-06-10 19:09  A_zjzj  阅读(26)  评论(0编辑  收藏  举报