思路 : 就是建出基环树 , 然后树上差分 , 再处理环上无限循环 .
为啥会 Wa ( 样例都过不去 ) :
/*
这个显然构成了一棵基环树
每个节点分开贡献
*/
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=2e5+10,MOD=998244353;
int n,k,to[MAXN],v[MAXN],vis[MAXN],ans[MAXN],flg[MAXN],cir[MAXN];
int fa[MAXN][21],dis[MAXN],anc[MAXN],pre[MAXN];
vector<int> g[MAXN];
vector<int> cirans[MAXN];
int qpow(int base,int p) {
int ans=1;
while(p) {
if(p&1) ans=ans*base%MOD;
base=base*base%MOD,p>>=1;
}
return ans;
}
int revid[MAXN],pos[MAXN],len[MAXN]; //记录每个点所在环 , 在环上的位置 , 环的长度
void solve(int u) {
if(vis[u]) return ;
vis[u]=1; if(cir[u]) return dis[u]=0,anc[u]=u,void();
solve(to[u]),fa[u][0]=to[u];
ffor(i,1,19) fa[u][i]=fa[fa[u][i-1]][i-1];
dis[u]=dis[to[u]]+1,anc[u]=anc[to[u]];
return ;
}
void add(int cirid,int startpos,int v,int Len) {
int reg=Len/len[cirid];
cirans[cirid][1]=(cirans[cirid][1]+reg%MOD*v%MOD)%MOD;
int rst=Len-reg*len[cirid]; if(rst==0) return ;
if(len[cirid]-startpos+1>=rst) {
cirans[cirid][startpos]=(cirans[cirid][startpos]+v)%MOD;
cirans[cirid][startpos+rst]=(cirans[cirid][startpos+rst]-v)%MOD;
}
else {
cirans[cirid][startpos]=(cirans[cirid][startpos]+v)%MOD;
int nxt=rst-len[cirid]+startpos-1;
cirans[cirid][1]=(cirans[cirid][1]+v)%MOD;
cirans[cirid][nxt+1]=(cirans[cirid][nxt+1]-v)%MOD;
}
return ;
}
void dfs(int u) {
for(auto v:g[u]) {
dfs(v);
pre[u]=(pre[v]+pre[u])%MOD;
}
return ;
}
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>k;
ffor(i,1,n) cin>>to[i];
ffor(i,1,n) cin>>v[i];
ffor(i,1,n) if(!flg[i]) {
int u=i;
while(!flg[u]) flg[u]=1,u=to[u];
while(!cir[u]) cir[u]=1,u=to[u];
}
ffor(i,1,n) if(!cir[i]) g[to[i]].push_back(i);
ffor(i,1,n) if(!vis[i]) solve(i);
memset(vis,0,sizeof(vis));
int cirsum=0;
ffor(i,1,n) if(cir[i]&&!vis[i]) {
++cirsum;
cirans[cirsum].push_back(0);
int u=i,tmp=0;
while(!vis[u]) vis[u]=1,revid[u]=cirsum,pos[u]=++tmp,u=to[u],cirans[cirsum].push_back(0);
cirans[cirsum].push_back(0),len[cirsum]=tmp;
}
ffor(i,1,n) {
if(dis[i]>=k) {
int u=i;
roff(j,19,0) if(k&(1<<j)) u=fa[u][j];
pre[fa[u][0]]=(pre[fa[u][0]]-v[i])%MOD,pre[fa[i][0]]=(pre[fa[i][0]]+v[i])%MOD;
}
else {
int u=i;
pre[fa[i][0]]=(pre[fa[i][0]]+v[i])%MOD;
u=to[anc[i]],add(revid[u],pos[u],v[i],k-dis[i]);
}
}
ffor(i,1,cirsum) ffor(j,1,len[i]) cirans[i][j]=(cirans[i][j]+cirans[i][j-1])%MOD;
k%=MOD;
k=qpow(k,MOD-2);
ffor(i,1,n) if(cir[i]) dfs(i);
ffor(i,1,n) {
int ans=pre[i];
if(cir[i]) ans=ans+cirans[revid[i]][pos[i]];
ans%=MOD,ans+=MOD,ans%=MOD;
ans*=k,ans%=MOD;
cout<<ans<<' ';
}
return 0;
}
调出来我给你几个关注 !