codevs1009

题目地址:http://codevs.cn/problem/1009/

分析:

【TAG】FLOYD,乘法原理,高精度

【构思】

求可变换数的个数,那么就是组合数学的内容,四个原理的应用;

假如能知道每位的变换个数,那么乘起来就是结果;

于是用FLOYD来求传递闭包,每个数可以变换成其他哪些数,然后累加;

最后相乘,注意要高精度;

【小结】

1、求个数:组合数学,最本质的求法其实就是加法原理、减法原理、乘法原理和除法原理

2、对于超长的数字,当做字符串处理

3、求连通个数的问题,用Floyd求出传递闭包后解决

代码:

var a,ans:array[1..30] of longint;
f:array[0..9] of longint;
g:array[0..9,0..9] of boolean;
m,n,i,j,t,k:longint;
s:string;
begin
fillchar(g,sizeof(g),false);
fillchar(f,sizeof(f),0);
fillchar(ans,sizeof(ans),0);
readln(s);
n:=0; m:=0; i:=1;
while s[i] in [‘0‘..‘9‘] do
begin
inc(n); a[n]:=ord(s[i])-48; inc(i);
end;
while i<=length(s) do
begin
if s[i] in [‘0‘..‘9‘] then m:=m*10+ord(s[i])-48;
inc(i);
end;
for i:=1 to m do
begin
readln(t,j); g[t,j]:=true;
end;
for k:=0 to 9 do
for i:=0 to 9 do
for j:=0 to 9 do
g[i,j]:=g[i,j] or (g[i,k] and g[k,j]);
for i:=0 to 9 do g[i,i]:=true;
for i:=0 to 9 do
for j:=0 to 9 do
inc(f[i],ord(g[i,j]));
ans[1]:=1;
for k:=1 to n do
begin
j:=0;
for i:=1 to 30 do
begin
ans[i]:=ans[i]*f[a[k]]+j;
j:=ans[i] div 10;
ans[i]:=ans[i] mod 10;
end;
end;
j:=30;
while ans[j]= 0 do dec(j);
for i:=j downto 1 do write(ans[i]);
writeln;
end. 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-28 20:31:03

codevs1009的相关文章

codevs1009 产生数

题目描述 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次或多次),能产生出多少个不同整数. 仅要求输出个数. 输入描述 In

【日常学习】【floyd传递闭包+高精】codevs1009 产生数题解

题目描述 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次或多次),能产生出多少个不同整数. 仅要求输出个数. 输入描述