ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#203403 | #3560. 小院闲窗春色深 | snow_trace | 100 | 1683ms | 17372kb | C++11 | 6.1kb | 2024-02-24 11:34:51 | 2024-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
*/
Details
小提示:点击横条可展开更详细的信息
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