洛谷P1037 [NOIP2002 普及组] 产生数

排列组合 QWQ

当我第一眼看见这到题,K 才 15???,于是默默的打出了暴搜。
以我这么高(la)超(ji)的水平,当然是
TLE.....
对着屏幕一呆,70行代码。。。。

步入正题:

再打深搜,那是不可能的。
发现:总方案数不就是对于每一个数的方案数乘起来吗?

注意

  1. 对于数字a,b,c, 若a可以变成b,b可以变成c,那么a就可以变成c。如何解决呢?_____(水水的floyd)。
  2. 注意到(n < \(10^{30}\)) 。 所以...高精度?(没错)no~ no~ no~,可以用__int128。

算法设计:

  1. 读入,顺便将u , v存入二维表\(vis\), \(vis[i][j]\)表示 i 到 j是否可变。
  2. 跑一遍floyd;
  3. 将点 i (0 <= i <= 9)的出度个数用be[]数组存起来。
  4. ans将\(be[i]\) 一个一个乘起来
  5. 完美输出

AC Code:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
const int N = 100,INF=1e9,mod=INF+7;
int be[N];
bool vis[N][N];

__int128 read()
{
    __int128 f=1,w=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
        f=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        w=w*10+ch-'0';
        ch=getchar();
    }
    return f*w;
}
void print(__int128 x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
int main()
{
	__int128 ans=1,n;
	int k,a,b;
	n = read();
	cin >> k;
	rep(i,1,k){
		cin >> a >> b;
		vis[a][b] = 1;
	}
	rep(k,0,9)rep(i,0,9)rep(j,0,9)if(i==j || (vis[i][k] && vis[k][j]))vis[i][j] = true;
	rep(i,0,9)
		rep(j,0,9)
			if(vis[i][j])be[i]++;	
	while(n){
		ans *= be[n%10];	
		n/=10;
	}
	print(ans);	
	return 0;
}

记得点个赞哟~~

posted @ 2022-08-18 14:17  weirdoX  阅读(129)  评论(0)    收藏  举报