loj3381. 「CSP-S 2020」函式呼叫
阿新 • • 發佈:2021-09-30
詐騙題。看起來很像資料結構,事實上是個圖論。
題目明確說明呼叫關係是一個 DAG,考慮拓撲排序。
不難發現乘法的本質上是將加法操作重複了若干次,於是我們可以考慮把所有操作都轉化為加法操作。
每個加法的貢獻次數是他後面所有乘法操作的乘積,我們可以直接在 DAG 上面 dp 出每一個 3 型別函式內部執行到第 \(i\) 個呼叫的時候的乘法操作字尾積,然後再拓撲排序求出每個加法操作在這個序列裡面會被執行多少次,然後直接把貢獻加到變數上面就好了。
#include<iostream> #include<cstdio> #include<vector> #include<queue> using namespace std; #define int long long const int mod=998244353; struct function { int opt,pos,val; vector<int> son; }fun[1000001]; int n,m,p,a[1000001],d[1000001],sum[1000001]; vector<int> f[1000001],v[1000001]; bool vis[1000001]; inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x; } void print(int x) { if(x>=10) print(x/10); putchar(x%10+'0'); } inline void dfs(int k) { vis[k]=1; if(fun[k].opt==1) { f[k].push_back(1); f[k].push_back(1); return; } if(fun[k].opt==2) { f[k].push_back(fun[k].val); f[k].push_back(1); return; } for(auto i:fun[k].son) { if(!vis[i]) dfs(i); f[k].push_back(f[i][0]); } for(register int i=f[k].size()-2;~i;--i) f[k][i]=f[k][i]*f[k][i+1]%mod; f[k].push_back(1); } inline void topo() { sum[m]=1; queue<int> q; for(register int i=1;i<=m;++i) if(!d[i]) q.push(i); while(!q.empty()) { int k=q.front(); q.pop(); int j=0; for(auto i:fun[k].son) { ++j; if(!--d[i]) q.push(i); if(!vis[k]) continue; sum[i]=(sum[i]+sum[k]*f[k][j]%mod)%mod; } } } signed main() { n=read(); for(register int i=1;i<=n;++i) a[i]=read(); m=read(); for(register int i=1;i<=m;++i) { fun[i].opt=read(); if(fun[i].opt==1) fun[i].pos=read(),fun[i].val=read(); if(fun[i].opt==2) fun[i].val=read(); if(fun[i].opt==3) { p=read(); while(p--) { fun[i].son.push_back(read()); ++d[fun[i].son.back()]; } } } p=read(); ++m; for(register int i=1;i<=p;++i) { fun[m].son.push_back(read()); ++d[fun[m].son.back()]; } dfs(m); topo(); for(register int i=1;i<=n;++i) a[i]=(a[i]*f[m][0])%mod; for(register int i=1;i<=m;++i) if(fun[i].opt==1) a[fun[i].pos]=(a[fun[i].pos]+sum[i]*fun[i].val%mod)%mod; for(register int i=1;i<=n;++i) { print(a[i]); putchar(' '); } puts(""); return 0; }