UOJ Logo

NOI.AC

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#203403#3560. 小院闲窗春色深snow_trace1001683ms17372kbC++116.1kb2024-02-24 11:34:512024-02-24 13:07:12

answer

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int n,m;
int dis[405][405],ok[405][405],dd[405][405];
int pre[500005],suf[500005];
int h[405],h1[405];//总方案数,总方案数的权值和
int g[405],g1[405];//不成立的方案数,不成立的方案数的权值和。
int f[405],f1[405];
//每次转移考虑枚举 1 所在的连通块大小
int inv[500005],jie[500005];
int s1[505],s2[505],s3[505];//不带m的方案数和随便的方案数和必须带m的方案数
int q1[500005],q2[500005],q3[500005];int tot = 0;
int qp(int p,int q){
	int ans = 1,pro = p%mod;
	while(q){
		if(q&1)ans = ans*(pro)%mod;
		pro = pro*pro%mod;q>>=1;
	}return ans;
}int C(int n,int m){
	if(m>n)return 0;
	return jie[n]*inv[m]%mod*inv[n-m]%mod;
}int pw[200005];
void init(){
	memset(s1,0,sizeof(s1));memset(s2,0,sizeof(s2));memset(f,0,sizeof(f));memset(f1,0,sizeof(f1));
	pw[0] = 1;for(int i = 1;i<=n*n;i++)pw[i] =pw[i-1]*(m)%mod;
	for(int i = 1;i<=n;i++){
		h[i] = qp(2,i*(i-1)/2);h1[i] = qp(m+1,i*(i-1)/2);
		//for(int j =0;j<=i*(i-1)/2;j++){
		//	h1[i] = (h1[i]+pw[j]*C(i*(i-1)/2,j))%mod;
		//}
	}f[1] = 1,f1[1] = 1,g[1] = 0,g1[1]=  0;
	for(int i = 2;i<=n;i++){g[i] = g1[i] = 0;
		for(int k = 1;k<i;k++){
			g[i] += C(i-1,k-1)*f[k]%mod*h[i-k]%mod;
			g1[i] += C(i-1,k-1)*f1[k]%mod*h1[i-k]%mod*pw[k*(i-k)]%mod;
			g[i]%=mod,g1[i]%=mod;
		}f[i] = (h[i]-g[i]+mod)%mod,f1[i] = (h1[i]-g1[i]+mod)%mod;
	}//牛魔,怎么记录的方案数没有用啊。没事就放在那里吧。
	for(int i = 1;i<=n;i++)s2[i] =  f1[i],s3[i] = f1[i];
	pw[0] = 1;for(int i = 1;i<=n*n;i++)pw[i] =pw[i-1]*(m-1)%mod;
	for(int i = 1;i<=n;i++){
		h[i] = qp(2,i*(i-1)/2);h1[i] = qp(m,i*(i-1)/2);
	}f[1] = 1,f1[1] = 1,g[1] = 0,g1[1]=  0;
	for(int i = 2;i<=n;i++){g[i] = g1[i] = 0;
		for(int k = 1;k<i;k++){
			g[i] += C(i-1,k-1)*f[k]%mod*h[i-k]%mod;
			g1[i] += C(i-1,k-1)*f1[k]%mod*h1[i-k]%mod*pw[k*(i-k)]%mod;
			g[i]%=mod,g1[i]%=mod;
		}f[i] = (h[i]-g[i]+mod)%mod,f1[i] = (h1[i]-g1[i]+mod)%mod;
	}for(int i = 1;i<=n;i++)s1[i] = f1[i],s3[i] = (s3[i]-f1[i]+mod)%mod;
}
vector<int>p[405];int col[405],sz[405],nw;
void dfs(int now){col[now] = nw;
	for(int i =0;i<p[now].size();i++){
		if(!col[p[now][i]])dfs(p[now][i]);
	}
}
void solve(int id){
		cin >> n >> m;nw = 0;init();
		for(int i = 1;i<=n;i++)sz[i] = col[i] = 0;
		for(int i = 1;i<=n;i++)p[i].clear();

		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=n;j++){
				cin >> dis[i][j];
				if(dis[i][j] == 0){
					p[i].push_back(j),p[j].push_back(i);
				}
			}
		}//if(id == 42){
		//	cout << n << " " << m << '\n';
		//	for(int i = 1;i<=n;i++){
		//	for(int j = 1;j<=n;j++){
		//		cout << dis[i][j] << " ";
		//	}cout << '\n';
		//}}return;
		for(int i = 1;i<=n;i++)for(int j =1;j<=n;j++){
			if(dis[i][j]>m){
				cout << 0 << endl;return;
			}if(dis[i][j]!=dis[j][i]){
				cout << 0 << endl;return;
			}
		}
		for(int i = 1;i<=n;i++)if(!col[i])nw++,dfs(i);
		for(int i = 1;i<=nw;i++){
			vector<int>pp;
			for(int j =1;j<=n;j++)if(col[j] == i)pp.push_back(i);int ok = 1;
			sz[i] = pp.size();
			for(int i = 1;i<pp.size();i++){
				for(int j = 1;j<=n;j++){
					if(dis[pp[i]][j]!=dis[pp[0]][j]){ok =0;break;}
				}
			}if(!ok){
				cout << 0 << endl;return;
			}
		}for(int i = 1;i<=n;i++){
			for(int j = 1;j<=n;j++){
				dd[col[i]][col[j]] = dis[i][j];
			}
		}memcpy(dis,dd,sizeof(dd));n = nw;
		for(int i = 1;i<=n;i++)for(int j = 1;j<=n;j++)ok[i][j] =0;
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=n;j++){
				if(i == j)continue;
				for(int k = 1;k<=n;k++){
					if(k == i or k == j)continue;
					if(dis[i][j] == dis[i][k]+dis[k][j]){
				//		cout << i << " " << j << " " << k << " " << dis[i][k]+dis[k][j] << endl;
						ok[i][j] = 1;break;
					}if(dis[i][j]>dis[i][k]+dis[k][j]){
						cout << 0 << endl;return;
					}
				}
			}
		}
	int okk = 0;tot =0 ;
	for(int i = 1;i<=n;i++){
		q1[++tot] = s1[sz[i]],q2[tot] = s2[sz[i]],q3[tot] = s3[sz[i]];
	}
	for(int i= 1;i<=n;i++){
		for(int j = i+1;j<=n;j++){
			if(!ok[i][j]){
				int tt = sz[i]*sz[j],ans = 0;
				for(int k = 1;k<=tt;k++){
					//枚举第一个等于最小值的位置
					ans+=qp(m-dis[i][j],k-1)*qp(m-dis[i][j]+1,tt-k)%mod;ans%=mod;
				}q2[++tot] = ans;ans =0 ;
				for(int k = 1;k<=tt;k++){
					ans+=qp(m-dis[i][j]-1,k-1)*qp(m-dis[i][j],tt-k)%mod;ans%=mod;
				}q1[tot] = ans;q3[tot] = (q2[tot]-q1[tot]+mod)%mod;
			}else{
				int tt = sz[i]*sz[j],ans =0 ;
				q2[++tot] = qp(m-dis[i][j]+1,tt);q1[tot] = qp(m-dis[i][j],tt);
				q3[tot] = (q2[tot]-q1[tot]+mod)%mod;
			}
			if(!ok[i][j] and dis[i][j] == m){
				okk = 1;
			}
		}
	}if(okk == 1){
		int ans = 1;
		for(int i = 1;i<=tot;i++)ans = ans*q2[i]%mod;
		cout << ans << endl;
	}else{
		pre[0] = suf[tot+1] = 1;
	//	for(int i = 1;i<=tot;i++)cout << " " << q1[i] << " " << q2[i] << " " << q3[i] << endl;
		for(int i = 1;i<=tot;i++)pre[i] = pre[i-1]*q1[i]%mod;
		for(int i = tot;i>=1;i--)suf[i] = suf[i+1]*q2[i]%mod;
		int ans = 0;
		for(int i = 1;i<=tot;i++)ans += pre[i-1]*q3[i]%mod*suf[i+1]%mod,ans%=mod;
		cout << ans << endl;
	}
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);;
	jie[0] = inv[0] = 1;for(int i= 1;i<=500000;i++)jie[i] = jie[i-1]*i%mod,inv[i] = qp(jie[i],mod-2);
	int t;cin >> t;
	for(int i =1;i<=t;i++){
		solve(i);
	}

	return 0;
}
/*
回来吧刺激小院闲窗春色深
历历在目的小院闲窗春色深,重帘未卷影沉沉莫名在流淌。
依稀记得倚楼无语理瑶琴,还有给力的远岫出云催薄暮。
把细风吹雨弄轻阴都给打退,就算梨花欲谢恐难禁也不累。
感觉硬贴进来不是很应景。

直接考虑有哪些边是在某个最短路里的,然后这些边权就确定了,其他的任意
然后我们直接钦定最早的m在哪里。

牛魔,咋还有0的情况。
真牛魔难。
首先把距离为0的缩点,中间判无解
然后考虑距离为0的连通块内部有多少种连边方式
dp,参考带标号无向连通图计数,加上权值
处理最大值为m只需要单步容斥。
1
4 2
0 1 1 2
1 0 1 1
2 1 0 2
2 1 2 0


*/

详细

小提示:点击横条可展开更详细的信息

Test #1:

score: 10
Accepted
time: 90ms
memory: 10468kb

input:

204
3 3
0 2 1
2 0 3
1 3 0
3 5
0 3 4
3 0 1
4 1 0
4 5
0 1 1 3
1 0 2 4
1 2 0 4
3 4 4 0
4 5
0 2 3 3
2 0 ...

output:

1
1
13
1
4
4
0
0
18
7
0
1
1
0
2
0
13
0
4
4
0
18
7
0
0
1
0
1
1
3
0
0
1
0
1
1
1
1
1
1
1
1
0
1
1
0
0
1
...

result:

ok 204 numbers

Test #2:

score: 10
Accepted
time: 87ms
memory: 10732kb

input:

20
36 744373192
0 9312648 15440508 12836339 12090822 11814833 6490999 13847739 7862103 20584369 8561...

output:

661143199
508590528
837677780
135769368
10300994
164629851
853271557
642677104
785643498
837491821
9...

result:

ok 20 numbers

Test #3:

score: 5
Accepted
time: 197ms
memory: 17372kb

input:

2
400 1000000000
0 13808551 19328904 17405838 21149586 15404044 7866869 11422830 12942958 21193652 1...

output:

626881850
344046232

result:

ok 2 number(s): "626881850 344046232"

Test #4:

score: 5
Accepted
time: 190ms
memory: 17372kb

input:

2
400 1000000000
0 14770595 11960705 14167217 16875028 4062400 16938709 10974424 14779359 10201441 1...

output:

831783370
613181630

result:

ok 2 number(s): "831783370 613181630"

Test #5:

score: 5
Accepted
time: 191ms
memory: 17372kb

input:

2
400 1000000000
0 19670766 11305909 13777445 13208147 10981829 14581204 14947677 23051829 11830974 ...

output:

459514299
868236763

result:

ok 2 number(s): "459514299 868236763"

Test #6:

score: 5
Accepted
time: 200ms
memory: 17368kb

input:

2
400 1000000000
0 17723139 18222708 16934888 13023334 20268472 16395805 16596042 18027449 18601832 ...

output:

36755219
682293912

result:

ok 2 number(s): "36755219 682293912"

Test #7:

score: 20
Accepted
time: 112ms
memory: 14936kb

input:

2
398 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...

output:

269676500
218314154

result:

ok 2 number(s): "269676500 218314154"

Test #8:

score: 20
Accepted
time: 86ms
memory: 10568kb

input:

20
31 606668000
0 63776809 28098165 18927177 45964474 59245929 45964474 63776809 59245929 32851078 4...

output:

723771478
894028931
807934521
338045047
445442568
155627530
884657725
979980638
214630018
56377231
8...

result:

ok 20 numbers

Test #9:

score: 5
Accepted
time: 136ms
memory: 13952kb

input:

2
400 1000000000
0 9493556 3729536 15672132 6459545 6567649 4203273 2659943 8338120 3764957 5839726 ...

output:

23513587
596758462

result:

ok 2 number(s): "23513587 596758462"

Test #10:

score: 5
Accepted
time: 132ms
memory: 14140kb

input:

2
400 1000000000
0 4548100 5592201 6703474 1939013 2274200 1382749 2099318 2755020 2618761 3211869 6...

output:

257976477
541722834

result:

ok 2 number(s): "257976477 541722834"

Test #11:

score: 5
Accepted
time: 128ms
memory: 14160kb

input:

2
400 1000000000
0 14681334 8111719 7636981 10525492 5749614 10040863 8111719 9502166 7228179 811171...

output:

362571923
270871151

result:

ok 2 number(s): "362571923 270871151"

Test #12:

score: 5
Accepted
time: 134ms
memory: 13884kb

input:

2
400 1000000000
0 1294054 4015981 4550486 1232581 2472119 5603920 3007990 7944606 1294054 5346303 3...

output:

364141400
649756260

result:

ok 2 number(s): "364141400 649756260"

Extra Test:

score: 0
Extra Test Passed