1. 程式人生 > 其它 >loj3381. 「CSP-S 2020」函式呼叫

loj3381. 「CSP-S 2020」函式呼叫

題目連結

詐騙題。看起來很像資料結構,事實上是個圖論。

題目明確說明呼叫關係是一個 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;
}