P1037 [NOIP2002 普及组] 产生数

Portal.

注意到数与数之间的转换关系是连续的,即若有 i → j , j → k i\rightarrow j,j\rightarrow k ij,jk,就有 i → k i\rightarrow k ik

发现和传递闭包很像,可以用 Floyd 算法解决。

由于数据范围 n < 1 0 30 n<10^{30} n<1030,要用 __int128

注意 Floyd 枚举中转点的循环要放在最外面。,这样可以保证每次转移时的信息是充分的。

#include 
using namespace std;

void write(__int128 x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}

__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;
}

bool f[15][15];
int deg[15];

int main()
{
	__int128 n=read();
	int kk;cin>>kk;
	while(kk--)
	{
		int x,y;cin>>x>>y;
		f[x][y]=1;
	}
	__int128 ans=1;
	for(int i=0;i<10;i++) f[i][i]=1;
	for(int k=0;k<10;k++)
		for(int i=0;i<10;i++)
			for(int j=0;j<10;j++)
				 f[i][j]|=(f[i][k]&f[k][j]);
	for(int i=0;i<10;i++)
		for(int j=0;j<10;j++) if(f[i][j]) deg[i]++;
	while(n) ans*=deg[n%10],n/=10;
	write(ans);
	return 0;
}

你可能感兴趣的:(题解,图论)