洛谷 P1037 产生数
Description
给出一个整数n(n<10^30)和k个变换规则(k≤15)
规则:
一位数可变换成另一个一位数:
规则的右部不能为零。
例如:n=234。有规则(k=2):
2->5
3->6
上面的整数234经过变换后可能产生出的整数为(包括原数):
234
534
264
564
共4种不同的产生数
问题:
给出一个整数 n 和k 个规则。
求出:
经过任意次的变换(0次或多次),能产生出多少个不同整数。
仅要求输出个数。
Input
键盘输入,格式为:
nk
x1y1
x2y2
... ..
xnyn
Output
屏幕输出,格式为:
1个整数(满足条件的个数):
Sample Input
234 2 2 5 3 6
Sample output
4
题解:
- 这题是一个乘法原理 + dfs
- 首先容易发现只需求出每位的变化数相乘即可。
- 对于变化规则建图,然后用dfs,就可以找出每位的变化数了
- 另:此题最后一个点要用高精度,我偷懒就用了 int128, int128的注意事项在代码结尾处
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#define int __int128
#define maxn 25
using namespace std;
struct E {int next, to;} e[maxn];
string n;
int k, cnt, ans = 1, num;
int h[maxn];
bool vis[maxn];
int read()
{
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x;
}
void print(int x)
{
if(x < 0) putchar('-'), x = -x;
if(x >= 10) print(x / 10);
putchar(x % 10 + 48);
}
void add(int u, int v)
{
e[++num].next = h[u];
e[num].to = v;
h[u] = num;
}
void dfs(int x)
{
vis[x] = 1, cnt++;
for(int i = h[x]; i != 0; i = e[i].next)
if(!vis[e[i].to]) dfs(e[i].to);
}
signed main()
{
cin >> n, k = read();
for(int i = 1; i <= k; i++)
{
int u = read(), v = read();
if(v) add(u, v);
}
int len = (int)n.size();
for(int i = 0; i < len; i++)
{
cnt = 0, memset(vis, 0, sizeof(vis)), vis[0] = 1;
int t = n[i] - '0';
dfs(t);
ans *= cnt;
}
print(ans);
return 0;
}
/*
用__int128有以下几点要注意
1. 比赛不能用
2. int main改为signed main
3. 输入输出要自己写
*/