原题链接
P1037
题目类型:
普
及
+
/
提
高
{\color{green}{普及+/提高}}
普及+/提高
AC记录:Accepted
题目大意
给定一个数字 n n n和 k k k个规则,规则的内容是可以让一个一位数变成另一个一位数,求在这些规则下,可能产生多少个数(包括自己)。
输入格式
第一行两个整数
n
,
k
n,k
n,k。
接下来
k
k
k行,每行两个整数
x
i
,
y
i
x_i,y_i
xi,yi,代表可以从
x
i
x_i
xi转换成
y
i
y_i
yi。
输出格式
输出能生成的数字个数。
S
a
m
p
l
e
\mathbf{Sample}
Sample
I
n
p
u
t
\mathbf{Input}
Input
234 2
2 5
3 6
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
4
H
i
n
t
&
E
x
p
l
a
i
n
\mathbf{Hint\&Explain}
Hint&Explain
在样例中,有以下
2
2
2个规则:
2
→
5
,
3
→
6
2\to 5,3\to 6
2→5,3→6。
则
234
234
234可以变成
234
,
534
,
264
,
564
234,534,264,564
234,534,264,564,总共
4
4
4种,答案为
4
4
4。
数据范围
对于 100 % 100\% 100%的数据, 1 ≤ n ≤ 1 0 30 , 1 ≤ k ≤ 15 1≤n≤10^{30},1≤k≤15 1≤n≤1030,1≤k≤15。
解题思路
我第一次看到这道题时,就想着可以把可能变化到的数字个数乘起来,得到答案。
实际上,这种思路并没有错,但是难点在于:如何找出一个数字可能变化到的数字?
这里就要涉及到一个判断图中的两点是否连通的思路,这里用的是类似
F
l
o
y
e
d
Floyed
Floyed的算法。
你可以想,如果你像
F
l
o
y
e
d
Floyed
Floyed一样,枚举一个中间点,判断他可不可通的话,这里就要用一个式子:设
f
α
,
β
f_{\alpha,\beta}
fα,β为
0
0
0则
α
,
β
\alpha,\beta
α,β两点没有连边,为
1
1
1则
α
,
β
\alpha,\beta
α,β两点有连边,
k
k
k为中间点。则f[i][j] = f[i][j] || ( f[i][k] && f[k][j] )。f[i][k] && f[k][j]是判断
i
→
k
i\to k
i→k和
k
→
j
k\to j
k→j是否都相通,而前面用一个||都很清楚,只要可行,就可以设为true。
这样一来,数字是否相通的问题就解决了。
但是,有个问题,数字乘起来爆unsigned long long怎么办?开高精度。
或者根据我们机房的某位大佬
U
n
n
a
m
e
d
_
C
u
b
e
\mathrm{\color{grey}U\color{red}{nnamed\_Cube}}
Unnamed_Cube所说,本题可以用__int128_t水过。
最后,祝大家早日

上代码
#include<bits/stdc++.h>
using namespace std;
string s;
bool road[20][20];
int can_be[20];
int mul[10010];
int n;
int main()
{
cin>>s>>n;
for(int i=0; i<=9; i++)
road[i][i]=true;
for(int i=1; i<=n; i++)
{
int x,y;
cin>>x>>y;
road[x][y]=true;
}
for(int k=0; k<=9; k++)
for(int i=0; i<=9; i++)
for(int j=0; j<=9; j++)
road[i][j]=road[i][j]||(road[i][k]&&road[k][j]);
for(int i=0; i<=9; i++)
for(int j=0; j<=9; j++)
if(road[i][j])
can_be[i]++;
mul[10000]=1;
int up=0;
for(int i=0; i<s.size(); i++)
{
int num=can_be[s[i]-'0'];
for(int j=10000; j>=1; j--)
{
mul[j]=mul[j]*num+up;
up=mul[j]/10;
mul[j]%=10;
}
}
int pos=1;
while(pos<10000&&mul[pos]==0)
pos++;
for(; pos<=10000; pos++)
cout<<mul[pos];
cout<<endl;
return 0;
}
完美切题 ∼ \sim ∼
本文介绍了一种使用类似Floyd算法解决数字转换问题的方法,通过构建转换规则图来计算一个数字在特定规则下能够转换成的不同数字的数量。
716

被折叠的 条评论
为什么被折叠?



