zoukankan      html  css  js  c++  java
  • 题解 函数调用

    题解 函数调用

    题目链接

    考场上居然没有想出来,看来我真是降智了。

    题目分析

    首先可以认为最后调用的一大堆函数是一个函数,也就是说最后只会执行一个函数。

    分开考虑每个“将数据中的指定元素加上一个值”对数据造成的影响,当我们第 (i) 次操作执行了 (a_pgets a_p+v) 时,以后的每一个乘法操作都会对增加的 (v) 造成影响,因为 ((a_p+v) imes s=a_p imes s+v imes s) ,也就是说,如果我们可以知道后面进行的所有乘法操作究竟乘了多少的话,我们就可以直接得出这一次的加法操作给答案造成了多大的影响。

    如果一个函数 (u) 依次调用了 (v_1,v_2,dots,v_c) ,那么调用 (v_{i+1},dots,v_c) 的时候给数据中的每一个元素乘上的值就会对调用函数 (v_i) 时使用的所有加法操作都额外乘上一个值,所以我们可以先求出每个函数总共给所有元素乘上了多大的值,记为 (h_i) ,然后令 (u)(v_1,v_2,dots,v_c) 全部连一条边,其中 (u) 连向 (v_i) 的边的边权为 (prod_{j=i+1}^ch_{v_j}) ,这样的话 (u)(v) 的路径条数表示的就是函数 (u) 调用函数 (v) 的次数, (u)(v) 的某条路径上的边边权的乘积就是从某次通过函数 (u) 通过某种途径调用到函数 (v) 到这次调用函数 (u) 结束的过程中将数据整体乘以了多少,所有路径边权乘积的和就是如果仅调用一次函数 (u) 函数 (v) 给答案造成贡献时需要乘以的系数。

    求所有路径边权乘积的和直接 dp 就行了。

    参考代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ch() getchar()
    #define pc(x) putchar(x)
    using namespace std;
    template<typename T>void read(T&x){
    	static char c;static int f;
    	for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
    	for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
    }
    template<typename T>void write(T x){
    	static char q[65];int cnt=0;
    	if(x<0)pc('-'),x=-x;
    	q[++cnt]=x%10,x/=10;
    	while(x)
    		q[++cnt]=x%10,x/=10;
    	while(cnt)pc(q[cnt--]+'0');
    }
    const int maxn=100005,maxm=100005,maxq=100005,maxc=1100005,mod=998244353;
    int mo(const int x){return x>=mod?x-mod:x;}
    struct Edge{
    	int v,w,nt;
    	Edge(int v=0,int w=0,int nt=0):
    		v(v),w(w),nt(nt){}
    }e[maxc*2];
    int hd[maxm],num;
    void qwq(int u,int v){
    	e[++num]=Edge(v,0,hd[u]),hd[u]=num;
    }
    int d[maxm],q[maxm],CNT[maxm],a[maxn],TP[maxm],P[maxm],V[maxm],sm[maxm];
    int main(){
    	int n;read(n);
    	for(int i=1;i<=n;++i)
    		read(a[i]);
    	int m;read(m);
    	for(int i=1;i<=m;++i){
    		int op;read(op);
    		if(op==1){
    			TP[i]=1;read(P[i]),read(V[i]);
    		}
    		else if(op==2){
    			TP[i]=2;read(V[i]);
    		}
    		else{
    			int c;read(c);
    			for(int j=1;j<=c;++j){
    				int s;read(s);qwq(i,s);qwq(s,i);
    			}
    		}
    	}
    	int Q;read(Q);
    	for(int j=1;j<=Q;++j){
    		int s;read(s);qwq(m+1,s);qwq(s,m+1);
    	}
    	for(int i=2;i<=num;i+=2)++d[e[i].v];int fro=0,bac=0;
    	for(int i=1;i<=m+1;++i)if(d[i]==0)q[bac++]=i;
    	while(fro<bac){
    		int u=q[fro++];
    		if(TP[u]==2)sm[u]=V[u];
    		else sm[u]=1;
    		for(int i=hd[u];i;i=e[i].nt){
    			int v=e[i].v;
    			if(i&1){
    				e[i].w=sm[u];
    				sm[u]=1ll*sm[u]*sm[v]%mod;
    			}
    			else{
    				--d[v];
    				if(d[v]==0)q[bac++]=v;
    			}
    		}
    	}
    	for(int i=1;i<=n;++i)a[i]=1ll*a[i]*sm[m+1]%mod;
    	for(int i=1;i<=num;i+=2)++d[e[i].v];fro=bac=0;
    	for(int i=1;i<=m+1;++i)if(d[i]==0)q[bac++]=i;CNT[m+1]=1;
    	while(fro<bac){
    		int u=q[fro++];
    		if(TP[u]==1)a[P[u]]=mo(a[P[u]]+1ll*V[u]*CNT[u]%mod);
    		for(int i=hd[u];i;i=e[i].nt)if(i&1){
    			int v=e[i].v,w=e[i].w;
    			CNT[v]=mo(CNT[v]+1ll*CNT[u]*w%mod);
    			if((--d[v])==0)q[bac++]=v;
    		}
    	}
    	for(int i=1;i<=n;++i)
    		write(a[i]),pc(" 
    "[i==n]);
    	return 0;
    }
    
    
  • 相关阅读:
    Python:在一个moudle如何引入另一个moudle下面的包
    RobotFramework做自动化中,能定位到iFrame里面,怎么在iFrame里面输入文字?
    RobotFramework框架做自动化的过程中,遇到不能选择下拉框问题
    雕刻机虚拟仿真及上位机设计(Labview上位机+Proteus仿真)
    医学成像原理——NMR/MRI成像基础
    数字图像处理(二) 灰度变换与空域滤波
    数字图像处理(一) 数字图像基础
    Python爬虫笔记
    python数据分析-第一周
    pyhton-web开发
  • 原文地址:https://www.cnblogs.com/lsq147/p/13944477.html
Copyright © 2011-2022 走看看