题目描述
给出一个整数 �n 和 �k 个变换规则。
规则:
- 一位数可变换成另一个一位数。
- 规则的右部不能为零。
例如:�=234,�=2n=234,k=2。有以下两个规则:
- 2⟶52⟶5。
- 3⟶63⟶6。
上面的整数 234234 经过变换后可能产生出的整数为(包括原数):
- 234234。
- 534534。
- 264264。
- 564564。
共 44 种不同的产生数。
现在给出一个整数 �n 和 �k 个规则。求出经过任意次的变换(00 次或多次),能产生出多少个不同整数。
仅要求输出个数。
输入格式
第一行两个整数 �,�n,k,含义如题面所示。
接下来 �k 行,每行两个整数 ��,��xi,yi,表示每条规则。
输出格式
共一行,输出能生成的数字个数。
输入输出样例
输入 #1复制
234 2 2 5 3 6
输出 #1复制
4
说明/提示
对于 100%100% 数据,满足 �<1030n<1030,�≤15k≤15。
【题目来源】
NOIP 2002 普及组第三题
正经深搜解法
好的,我们先贴一个题面
P1037 Make Numbers (假装大家已经看完题面了
-
思路一: 如果考虑如果一个数一个数地记录
我觉得不行~
证明:显然易见得平凡,读者自证不难。
我们注意到
给出一个整数 �(�<1030)n(n<1030) 和 �k 个变换规则 �≤15k≤15。
不好意思,
QAQ好像……有点大,溜了溜了。
-
思路二: 那么我们考虑一位一位地转化然后再借助乘法原理乘起来
哦,你可真是个天才。 于是就有了以下代码:
#include<iostream>
using namespace std;
string qwq;
int s[33],num[33],k,nxt[33][16],qaq;
bool vis[10];
long long ans = 1;
void dfs(int x,int y)
//x指上一个到达的数,y指现在的
{
//机房神仙说传一个参数就可以,但宝宝不会QAQ
if(vis[y])return;//对于环状循环的处理
vis[x] = 1;//记忆化
qaq++;
for(int i = 1;i <= num[y];i++)
dfs(y,nxt[y][i]);
vis[x] = 0;//归零
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(NULL),cout.tie(NULL);
//看不懂可忽略,就是取消cin&cout前后摇
cin>>qwq>>k;
int len = qwq.size();
for(int i = 0;i < len;i++)
s[i + 1] = qwq[i] - '0';
for(int i = 1;i <= k;i++)
{
int x,y;
cin>>x>>y;
nxt[x][++num[x]] = y;
}
for(int i = 1;i <= len;i++)
{
qaq = 1;
for(int j = 1;j <= num[s[i]];j++)
dfs(s[i],nxt[s[i]][j]);
ans *= qaq;
}
cout<<ans;
}
恭喜你,八十分(别打了
-
于是我们又一次注意到了:
给出一个整数 �(�<1030)n(n<1030) 和 �k 个变换规则 �≤15k≤15。
完了,不会写高精乘高精,怎么办 来山东蓝翔挖掘机学校
那就高精乘低精呗hhh
AC Code:
#include<bits/stdc++.h>
using namespace std;
string qwq;
int s[33],num[33],k,nxt[33][16],qaq;
//万能头选手注意莫用next当数组名
bool vis[10];
int ans[33];
void dfs(int x,int y)
{
vis[x] = 1;
if(vis[y])return;
qaq++;
for(int i = 1;i <= num[y];i++)
dfs(y,nxt[y][i]);
}
void mul(){
int jw = 0;
for(int i = 30;i;i--)
{
ans[i] = ans[i] * qaq + jw;
jw = ans[i] / 10;
ans[i] %= 10;
}
}//根据原理手写一个就好了
int main()
{
ios::sync_with_stdio(0);
cin.tie(NULL),cout.tie(NULL);
ans[30] = 1;
cin>>qwq>>k;
int len = qwq.size();
for(int i = 0;i < len;i++)
s[i + 1] = qwq[i] - '0';
for(int i = 1;i <= k;i++)
{
int x,y;
cin>>x>>y;
nxt[x][++num[x]] = y;
}
for(int i = 1;i <= len;i++)
{
qaq = 1;
for(int j = 1;j <= num[s[i]];j++)
dfs(s[i],nxt[s[i]][j]);
memset(vis,0,sizeof(vis));
mul();
}
int l = 0;
for(;ans[l]==0;l++);//处理前导零
for(int i = l;i <= 30;i++)
cout<<ans[i];
return 0;
}
control,简写为Ctrl,扩写为:
唱,跳,rap,篮球.
您还敢Ctrl+C吗
欢迎批评指正
码字不易,良心小编,留赞再走。QAQ