Description

牛牛得到了一堆神奇的恶魔果实,每个恶魔果实都给了牛牛一个改变数字的能力,可以把数字a变成数字b,现在牛牛有一个数字x,他想知道吃完这n个恶魔果实后,他可以把数字x变成多少种的数。
注:每一个恶魔果实的能力可以重复使用多次,当然也可以不用,存在相同能力的恶魔果实.

Solution

莫名其妙wa了很多次,一开始思路是直接dfs,每个数字变或不变,for找当前的数字能否到达1~9数字
然后tle了,考虑从图论的角度,可以用floyd处理出每个数字之间能否相互到达。
之后运用乘法原理,即每位数字能够有多少种情况,撑起来就可以啦。
不要忘记自己能到到达自己,对给自己连上一条边。

Code

#include<bits/stdc++.h>
typedef long long ll;
const int N = 1e6 + 5;
const int mod = 1e4 + 7;
using namespace std;
int maze[15][15];
int g[15][15];
ll vis[15];
string now;
int len;
int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  int x, n;
  cin >> x >> n;
  while(x) {
    int tmp = x % 10;
    now += tmp + '0';
    x /= 10;
    maze[tmp][tmp] = 1;
    len++;
  }
  reverse(now.begin(), now.end());
  for(int i = 1; i <= n; i++) {
    int l, r;
    cin >> l >> r;
    maze[l][r]++;
  }
  for(int k = 0; k <= 9; k++) {
    for(int i = 0; i <= 9; i++) {
      for(int j = 0; j <= 9; j++) {
        maze[i][j] = maze[i][j] || (maze[i][k] && maze[k][j]);
      }
    }
  }
  for(int i = 0; i <= 9; i++) {
    for(int j = 0; j <= 9; j++) {
      if(maze[i][j]) {
        vis[i]++;
      }
    }
    //cout << i << ' ' << vis[i] << "\n";
  }
  ll ans = 1;
  for(int i = 0; i < now.size(); i++) {
    int p = now[i] - '0';
    ans *= (vis[p]);
    ans %= mod;
  }
  cout << ans << "\n";
  return 0;
}