【SSLGZ 1021】2002年分区联赛普级组之三 产生数

题目描述
给出一整数n(<=10^30),k个变化规则(如2->3表示2可变成3),问共有几种产生数。
样例输入
234 2
2 5
3 6
样例输出
4
算法讨论
本题的数据已经明确告诉我们不能用搜索,只用求个数的话我们可以采用乘法原理计数,用f数组表示每个数字包括自己可以变化的个数,把n存入一个字符串,那么总数就可以表示为f[st[1]]*f[st[2]]… *f[st[n]]。由于一个数可以直接或间接的转换成另一数,例如:1->2,2->3,那么1其实也可以转换为3,所以我们要将1->3这条路也标记上,具体算法是一个类似于Floyd的传递,下面的程序会体现出来。最后枚举一遍,若i到j为true就将f[i]加1。

var
  a:array[0..9,0..9] of boolean;
  f:array[0..9] of longint;
  i,j,k,n,m,x,y,l:longint;
  st,st1:string;
  s:real;
begin
  readln(st);
  l:=length(st);
  for i:=l downto 1 do
    if st[i]=' '
      then begin
             st1:=copy(st,i+1,l-i);
             delete(st,i,l-i+1);
             val(st1,m);
             break
           end;
  for i:=1 to m do
    begin
      read(x,y);
      a[x,y]:=true
    end;
  for k:=0 to 9 do
    for i:=0 to 9 do
      for j:=0 to 9 do
        a[i,j]:=a[i,j] or (a[i,k] and a[k,j]);          //传递
  for i:=0 to 9 do
    f[i]:=1;
  for i:=0 to 9 do
    for j:=0 to 9 do
      if (a[i,j]) and (i<>j)
        then inc(f[i]);
  s:=1; l:=length(st);
  for i:=1 to l do
    begin
      val(st[i],n);
      s:=s*f[n]
    end;
  write(s:0:0)
end.

这里写图片描述
Pixiv ID:31574858

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值