[ABC199F] Graph Smoothing题解

AT_abc199_f [ABC199F] Graph Smoothing

题目描述

有一个包含 NNN 个顶点和 MMM 条边的简单无向图。顶点编号为 111NNN,边编号为 111MMM
iii 条边连接顶点 XiX_iXi 和顶点 YiY_iYi。此外,顶点 iii 上最初写有整数 AiA_iAi
你需要进行 KKK 次如下操作:

  • MMM 条边中,等概率且相互独立地随机选择一条边。记该边连接的两个顶点上写的数的平均值为 xxx,然后将这两个顶点上的数都替换为 xxx

请你求出每个顶点 iiiKKK 次操作后所写数字的期望值,并按照注释中的要求对 109+710^9+7109+7 取模输出。

输入格式

输入以如下格式从标准输入给出。

NNN MMM KKK
A1A_1A1 A2A_2A2 A3A_3A3 …\dots ANA_NAN
X1X_1X1 Y1Y_1Y1
X2X_2X2 Y2Y_2Y2
X3X_3X3 Y3Y_3Y3
⋮\vdots
XMX_MXM YMY_MYM

输出格式

请输出 NNN 行。
iii 行输出第 iii 个顶点在 KKK 次操作后所写数字的期望值,按照注释中的要求对 109+710^9+7109+7 取模输出。

输入输出样例 #1

输入 #1

3 2 1
3 1 5
1 2
1 3

输出 #1

3
500000005
500000008

输入输出样例 #2

输入 #2

3 2 2
12 48 36
1 2
1 3

输出 #2

750000036
36
250000031

输入输出样例 #3

输入 #3

4 5 1000
578 173 489 910
1 2
2 3
3 4
4 1
1 3

输出 #3

201113830
45921509
67803140
685163678

说明/提示

注释

输出有理数时,首先将其表示为分数 yx\frac{y}{x}xy,其中 x,yx, yx,y 为整数,且 xxx 不能被 109+710^9+7109+7 整除(在本题的约束下总能做到)。
然后,输出唯一满足 0≤z≤109+60 \leq z \leq 10^9+60z109+6xz≡y(mod109+7)xz \equiv y \pmod{10^9+7}xzy(mod109+7) 的整数 zzz

约束条件

  • 2≤N≤1002 \leq N \leq 1002N100
  • 1≤M≤N(N−1)21 \leq M \leq \frac{N(N-1)}{2}1M2N(N1)
  • 0≤K≤1090 \leq K \leq 10^90K109
  • 0≤Ai≤1090 \leq A_i \leq 10^90Ai109
  • 1≤Xi≤N1 \leq X_i \leq N1XiN
  • 1≤Yi≤N1 \leq Y_i \leq N1YiN
  • 给定的图是简单图
  • 输入中的所有值均为整数

样例解释 1

  • 若唯一的一次操作选择了第 111 条边:顶点 1,2,31, 2, 31,2,3 上的数分别变为 2,2,52, 2, 52,2,5
  • 若唯一的一次操作选择了第 222 条边:顶点 1,2,31, 2, 31,2,3 上的数分别变为 4,1,44, 1, 44,1,4
    因此,操作后顶点 1,2,31, 2, 31,2,3 上的数的期望值分别为 3,32,923, \frac{3}{2}, \frac{9}{2}3,23,29
    将其按注释中的方式转化为 109+710^9+7109+7 下的表达,分别为 3,500000005,5000000083, 500000005, 5000000083,500000005,500000008

样例解释 2

  • 111 次操作选择第 111 条边时,顶点 1,2,31, 2, 31,2,3 上的数分别为 30,30,3630, 30, 3630,30,36
  • 222 次操作选择第 111 条边时,顶点 1,2,31, 2, 31,2,3 上的数分别为 30,30,3630, 30, 3630,30,36
  • 222 次操作选择第 222 条边时,顶点 1,2,31, 2, 31,2,3 上的数分别为 33,30,3333, 30, 3333,30,33
  • 111 次操作选择第 222 条边时,顶点 1,2,31, 2, 31,2,3 上的数分别为 24,48,2424, 48, 2424,48,24
  • 222 次操作选择第 111 条边时,顶点 1,2,31, 2, 31,2,3 上的数分别为 36,36,2436, 36, 2436,36,24
  • 222 次操作选择第 222 条边时,顶点 1,2,31, 2, 31,2,3 上的数分别为 24,48,2424, 48, 2424,48,24
    444 种情况各以 14\frac{1}{4}41 的概率发生,因此最终顶点 1,2,31, 2, 31,2,3 上的数的期望值分别为 1234,1444(=36),1174\frac{123}{4}, \frac{144}{4}(=36), \frac{117}{4}4123,4144(=36),4117

由 ChatGPT 4.1 翻译

思路

观察发现,k数值过大,而转移重复,所以考虑矩阵快速幂求解,设转移矩阵为a则:

    for(int i=1;i<=m;i++){
        cin>>u>>v;
        df[u]++;//标记抽到u概率
        df[v]++;
        s[u][v]=s[v][u]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i!=j){
                if(s[i][j]==1){
                    a.a[i][j]=pow2(2*m,mod-2);//标记抽到i-j概率
                }
            }
            else{
                a.a[i][j]=(1-df[i]*pow2(2*m,mod-2)%mod+mod)%mod;//类似
            }
        }
    }

代码见下

#include<bits/stdc++.h> 
using namespace std;
long long n,k,mod=1e9+7,s[105][105],u,v,op=0;
long long m,df[105];
struct mat{
	long long a[105][105];
}a,b,q;
mat kc(mat c1,mat c2){
	mat c;
	memset(c.a,0,sizeof(c.a));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				c.a[i][j]=(c.a[i][j]+c1.a[i][k]*c2.a[k][j])%mod;
			}
		}
	}
	return c;
}
mat abc(mat a2,long long m2){
	mat b2;
	memset(b2.a,0,sizeof(b2.a));
	for(int i=1;i<=n;i++){
		b2.a[i][i]=1;
	}
	while(m2!=0){
		if(m2%2==1){
			b2=kc(b2,a2);
		}
		a2=kc(a2,a2);
		m2/=2;
	}
	return b2;
}
long long pow2(long long a1,long long b1){
    long long k1=1;
    while(b1!=0){
        if(b1%2==1){
            k1=k1*a1%mod;
        }
        a1=a1*a1%mod;
        b1/=2;
    }
    return k1;
}
int main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){
		cin>>q.a[1][i];
	}
    for(int i=1;i<=m;i++){
        cin>>u>>v;
        df[u]++;
        df[v]++;
        s[u][v]=s[v][u]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i!=j){
                if(s[i][j]==1){
                    a.a[i][j]=pow2(2*m,mod-2);
                }
            }
            else{
                a.a[i][j]=(1-df[i]*pow2(2*m,mod-2)%mod+mod)%mod;
            }
        }
    }
	b=abc(a,k);
	for(int i=1;i<=n;i++){
        op=0;
		for(int j=1;j<=n;j++){
            op+=q.a[1][j]*b.a[j][i];
            op%=mod;
        }
        cout<<op<<endl;
	}
	return 0; 	
}
posted @ 2025-12-09 21:11  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源