P7077 [CSP-S2020] 函数调用
我们考虑如果没有第三种函数,如何解决这个问题。
发现,对于每个1(1类),我们考虑在它之后执行了多少个2,然后累乘,就是这个增加操作实际的贡献。我们只需要倒序,维护一个后缀积即可。
我们的核心思想就是计算每个1的贡献是几倍。
考虑有3会怎么样。还是延续上面的思路。有3,那么可以递归调用,我们记 \(mul_i\) 表示执行这个函数后,整个序列会而且恰好是DAG,我们发现母结点的乘积恰好等于自己的乘积 \(\times\) 所有后继乘积,可以用拓扑排序的逆序求解。
然后我们就要求解每个函数会被调用的次数了。我们发现母结点被调用一次,那么子节点就会相对应的调用多次(每次当母结点被调用一次,子节点调用次数是一样的)。我们先倒着求出所有第一层的函数调用的次数(即没有操作3的情况)。对于不在第一层的点,我们发现它的调用次数首先有一个基数 \(sum_{fa}\),然后对于它所有的兄弟节点,需要乘上在它之后的 \(mul_{brother}\)。这个处理是拓扑排序的正序。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
typedef long long ll;
const int N=100010,M=1000010,mod=998244353;
int n,w[N],m,d[N],q[N],g[N];
int h[N],e[M],ne[M],idx;//don't forget memset h!
void add(int a,int b){
++d[b],e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
struct Func{
int t,p,v,mul,sum;
}f[N];
void topo(){
int hh=0,tt=-1;
E(i, m)
if(!d[i])q[++tt]=i;
Wh(hh<=tt){
int x=q[hh++];
Ed{
int j=e[i];
if(--d[j]==0)q[++tt]=j;
}
}
}
void calc_mul(){
Re(i, m-1, 0){
int x=q[i];
Ed{
int j=e[i];
f[x].mul=1ll*f[x].mul*f[j].mul%mod;
}
}
}
void calc_sum(){
L(i, m){
int x=q[i];
ll sum=f[x].sum;
Ed{
int j=e[i];
f[j].sum=(f[j].sum+sum)%mod;
sum=sum*f[j].mul%mod;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
E(i, n)cin>>w[i];
cin>>m;
memset(h,-1,m*4+4);
E(i, m){
cin>>f[i].t;
if(f[i].t==1)cin>>f[i].p>>f[i].v;
else if(f[i].t==2)cin>>f[i].mul;
else{
int c;
cin>>c;
W(c){
int x;
cin>>x;
add(i,x);
}
}
}
topo();
E(i, m)
if(f[i].t!=2)f[i].mul=1;
calc_mul();
int q;
cin>>q;
ll mul=1;
E(i, q)cin>>g[i];
Re(i, q, 1){
int x=g[i];
f[x].sum=(f[x].sum+mul)%mod;
mul=mul*f[x].mul%mod;
}
calc_sum();
E(i, n)w[i]=w[i]*mul%mod;
E(i, m)
if(f[i].t==1)w[f[i].p]=(w[f[i].p]+1ll*f[i].sum*f[i].v%mod)%mod;
E(i, n)cout<<w[i]<<' ';
return 0;
}
标签:调用,int,sum,cin,函数调用,mul,mod
From: https://www.cnblogs.com/wscqwq/p/17751563.html