loj3381. 「CSP-S 2020」函数调用
诈骗题。看起来很像数据结构,事实上是个图论。
题目明确说明调用关系是一个 DAG,考虑拓扑排序。
不难发现乘法的本质上是将加法操作重复了若干次,于是我们可以考虑把所有操作都转化为加法操作。
每个加法的贡献次数是他后面所有乘法操作的乘积,我们可以直接在 DAG 上面 dp 出每一个 3 类型函数内部执行到第 个调用的时候的乘法操作后缀积,然后再拓扑排序求出每个加法操作在这个序列里面会被执行多少次,然后直接把贡献加到变量上面就好了。
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?