2020 CQ省选退役记

Day0

考试就在我们学校考…

下午还被拉去军体拳比赛舞旗。(实际上前两天都有被拉去训练)

晚上教练说就不回家了,在学校自习。然后有位巨佬溜了…其他人上到10点也溜了。只有我一个人是住读,10:50溜回寝室睡觉。

大概11:40睡着吧

Day1

考试就咕掉了每天的英语/语文早读。

然后7:20去了机房,发现考场门大开,没人。挺离谱的。

在没作考场的机房看了看模板,过了一会被赶下楼说7:50才能上楼。。。。

进考场。看题。

10分钟发现好像是个傻逼题,线段树上二分。 O ( n log ⁡ n ) O(n\log n) O(nlogn)

写到一半发现相同答案求最大位置有点难搞。还得再去线段树上二分一次。

然后去看T2,发现不会,只有30分。去看T3。

发现集合外的点如果能替代就连边,然后知道最终的大小关系。想起来就是一个保序回归问题的 L 2 L_2 L2

但是我从来没打过啊!

就看了论文的其中一节。

看看时间10点,还有3h,搏一搏单车变摩托。

然后就开写,整体二分+最小割。割边的值我直接设为修改代价。不知道对不对。

写到一半发现如果要满足题目还有不只每个点的大小,还有很多点线性组合的大小关系,然后有点懵逼。举了几个例子发现只考虑单点应该是对的。。。然后继续写。

写代码时肩好酸,舞旗太卖力了。

写完11.30。不过样例。完了。

调了一会发现是网络流写错了,变量重名。

居然过样例了。

大样例也过了。。。。一看大样例n=800,数据范围是1000,感觉应该大概螺旋稳(bushi)。反正暴力也写不来。就这样了。。。

回去写T1暴力,对拍,发现T1写错了。心态爆炸。

发现是数据造错了。改过来 拍上了。
(然后我nt没有测最大数据跑的时间,想着 O ( n log ⁡ n ) O(n\log n) O(nlogn)应该是复杂度下限了)

过了一会发现T2的m=0能写。多10分,变成40。

想了一会没想到 k i k^i ki怎么处理。不会了。

虚假的估分:100+40+100

Day1.5

下来问了问,好像zjx,wk都ak了。太强了。

然后xmy切T2了,太强了。

csq找出斯特林数的规律切T2了,太强了。

然后听说T1卡常,不开O2,本地要跑6、7秒。

有点慌。

教练问我T1卡不卡常,其实我没测,但是我支支吾吾应付过去了。

下午考场极域用不起,老师叫我们帮忙手动关机。然后我去自己的机子上改一下对拍的数据范围,测一测。

跑不出来。心肺停止。

过了一会发现是造数据数组忘了开大到2000000。。。然后测了一下跑了7、8秒。

感觉被卡常了。

问了问 log ⁡ 2 \log^2 log2的都只跑7s。感觉药丸。我还没写fread和快速输出。

要是挂到60就人没了。

本来CSP考的很菜。如果T3爆0,T1爆60,就只有60+40+0=100。当场退役。

看人品吧。估计会挂。

(退役也挺好,回去快乐文化课(bu shi))

下来看了一下wk大爷的T2做法,好神仙。但是uoj群都说T2一眼题。我太菜了还是退役吧。

原来T2的次幂可以转化成下降幂,然后下降幂用求导处理。QwQ。

@退役预定@ \Large\texttt{@退役预定@} @退役预定@

Day2

退役成功

T1 70 不会卡空间

T2 10分 傻逼原题不会

T3 50分 尝试写70没调出样例(自己出的)

舒服了 直接退役

洛谷上测了一下好像是:70 + 20 + 70

实际T2一定只有10分,如果T3运气好70,总分就是150。

貌似退役了 压线15名 但被女选手名额卡了

文化课我来了 Q . Q Q.Q Q.Q

放一下考场写的或者下来改了的代码:

D1T1

单点修改,查询两次线段树二分

洛谷上开O2能过 O ( n log ⁡ n ) O(n\log n) O(nlogn)

不小心开了long long

#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef double db;
void read(int &x) {
	char ch; while(!isdigit(ch=getchar()));
	for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
}
const int MAXN = 2000010;
int q, bin[MAXN], n;
struct node { int op, t, x, y; }a[MAXN];
LL sum[2][MAXN<<2];
void ins(int i, int l, int r, int x, int t, int v) {
	sum[t][i] += v;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(x <= mid) ins(i<<1, l, mid, x, t, v);
	else ins(i<<1|1, mid+1, r, x, t, v);
}
int find1(int i, int l, int r, LL s) {
	if(l == r) return l;
	int mid = (l + r) >> 1;
	if(sum[1][i<<1|1] >= s) return find1(i<<1|1, mid+1, r, s);
	return find1(i<<1, l, mid, s-sum[1][i<<1|1]);
}
struct mynode { LL ls, rs, val; mynode(LL l=0, LL r=0) { val = 2*min(ls=l, rs=r); } };
inline mynode gx(const mynode &A, const mynode &B) {
	return A.val == B.val ? (A.rs < B.rs ? A : B) : (A.val > B.val ? A : B);
}
mynode qry(int i, int l, int r, LL vl, LL vr) {
	if(l == r) return mynode(vl, vr+sum[1][i]);
	int mid = (l + r) >> 1;
	mynode re = mynode(vl+sum[0][i<<1], vr+sum[1][i<<1|1]);
	if(vl+sum[0][i<<1] <= vr+sum[1][i<<1|1]) re = gx(re, qry(i<<1|1, mid+1, r, vl+sum[0][i<<1], vr));
	else re = gx(re, qry(i<<1, l, mid, vl, vr+sum[1][i<<1|1]));
	return re;
}
int main () {
	freopen("icefire.in", "r", stdin);
	freopen("icefire.out", "w", stdout);
	read(q); bin[++n] = 0;
	for(int i = 1; i <= q; ++i) {
		read(a[i].op); --a[i].op;
		if(!a[i].op)
			read(a[i].t), read(a[i].x), read(a[i].y), bin[++n] = a[i].x;
		else read(a[i].t);
	}
	sort(bin + 1, bin + n + 1);
	n = unique(bin + 1, bin + n + 1) - bin - 1;
	bin[n+1] = bin[n] + 1; ++n;
	for(int i = 1; i <= q; ++i) {
		if(!a[i].op) {
			a[i].x = lower_bound(bin + 1, bin + n + 1, a[i].x) - bin;
			ins(1, 1, n, a[i].x-(!a[i].t), a[i].t, a[i].y);
		}
		else {
			int p = a[i].t;
			ins(1, 1, n, a[p].x-(!a[p].t), a[p].t, -a[p].y);
		}
		mynode ans = qry(1, 1, n, 0, 0);
		if(ans.val) {
			int pos = find1(1, 1, n, ans.rs);
			printf("%d %lld\n", bin[pos], ans.val);
		}
		else puts("Peace");
	}
}

D1T2

直接用第二类斯特林和组合数展开 k i k_i ki,然后推式子,不需要其他高级技巧。考试时没想到。 O ( m 2 ) O(m^2) O(m2)

这道题是下来改的。

#include 
using namespace std;
const int MAXM = 1005;
int pw[MAXM], C[MAXM], S[MAXM][MAXM];
int n, x, p, m;
inline int qpow(int a, int b) {
	int re = 1;
	for(; b; b>>=1, a=1ll*a*a%p)if(b&1)re=1ll*re*a%p;
	return re;
}
void pre() {
	C[0] = S[0][0] = 1;
	for(int i = 1; i <= m; ++i) {
		C[i] = 1ll * C[i-1] * (n-i+1) % p;
		for(int j = 1; j <= m; ++j)
			S[i][j] = (S[i-1][j-1] + 1ll * S[i-1][j] * j) % p;
	}
	int up = min(n, m); pw[up] = qpow(x+1, n-up);
	for(int i = up-1; i >= 0; --i) pw[i] = 1ll * pw[i+1] * (x + 1) % p;
}
int main () {
	scanf("%d%d%d%d", &n, &x, &p, &m); pre();
	int ans = 0;
	for(int i = 0, a; i <= m; ++i) {
		scanf("%d", &a); int t = 1;
		for(int j = 0; j <= i; ++j) {
			ans = (ans + 1ll * S[i][j] * C[j] % p * t % p * pw[j] % p * a) % p;
			t = 1ll * t * x % p;
		}
	}
	printf("%d\n", ans);
}

D1T3

猜结论:如果一个点能被集合外的替代就连边然后 L 2 L_2 L2保序回归。判断暴力线性基。不知道能不能过。反正过了大样例。

#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef double db;
template<class T>void read(T &x) {
	char ch; while(!isdigit(ch=getchar()));
	for(x=ch-'0';isdigit(ch=getchar());x=x*10+(ch-'0'));
}
const int MAXN = 1010;
const int MAXM = 70;
const int MAXE = MAXN*MAXM*2;
const int mxxxe = (MAXE+2000)*2;
const LL inf = 1ll<<50;
int n, m, tot, v[MAXN], a[MAXN], b[MAXN];
bool ina[MAXN], inb[MAXN];
ULL c[MAXN];
struct xxj {
	ULL p[65];
	void clear() { for(int i = 0; i < 64; ++i) p[i] = 0; }
	bool ins(ULL x) {
		for(int i = 0; i < 64; ++i)
			if(x>>i&1) {
				if(!p[i]) { p[i] = x; return 1; }
				x ^= p[i];
			}
		return 0;
	}
	bool mytry(ULL x) {
		for(int i = 0; i < 64; ++i)
			if(x>>i&1) {
				if(!p[i]) return 1;
				x ^= p[i];
			}
		return 0;
	}
}tmp;
struct edge { int u, v; }E[MAXE], tmpE[MAXE];
struct node { int i; }pt[MAXN], tmppt[MAXN];
int ans[MAXN];
int fir[MAXN], info[MAXN], to[mxxxe], nxt[mxxxe], cnt, S, T;
LL cp[mxxxe];
inline void mylink(int u, int v, LL cc) {
	to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; cp[cnt] = cc;
	to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt; cp[cnt] = 0;
}
inline LL sqr(LL x) { return x * x; }
int myq[MAXN], dis[MAXN];
bool bfs() {
	int ql = 0, qr = 0;
	memset(dis, -1, (T+1)<<2);
	dis[T] = 0; myq[qr++] = T;
	while(ql < qr) {
		int u = myq[ql++];
		for(int i = fir[u], v; i; i = nxt[i])
			if(cp[i^1] && !~dis[v=to[i]])
				dis[v] = dis[u] + 1, myq[qr++] = v;
	}
	return ~dis[S];
}
LL aug(int u, LL Max) {
	if(u == T) return Max;
	LL re = 0, delta;
	for(int v, &i = info[u]; i; i = nxt[i])
		if(cp[i] && dis[v=to[i]] + 1 == dis[u] && (delta = aug(v, min(Max-re, cp[i])))) {
			cp[i] -= delta, cp[i^1] += delta;
			if((re += delta) == Max) return Max;
		}
	return re;
}
void maxflow() {
	while(bfs())
		memcpy(info, fir, (T+1)<<2), aug(S, inf);
}
bool flg[MAXN];
void dfs(int u) {
	flg[u] = 1;
	for(int i = fir[u], v; i; i = nxt[i])
		if(!flg[v=to[i]] && cp[i]) dfs(v);
}
void solve(int vl, int vr, int pl, int pr, int el, int er) {
	if(pl > pr) return;
	if(vl == vr) {
		for(int i = pl; i <= pr; ++i) ans[pt[i].i] = vl;
		return;
	}
	int mid = (vl + vr) >> 1;
	cnt = 1; S = n+1, T = n+2; fir[S] = fir[T] = 0;
	for(int i = pl; i <= pr; ++i) {
		fir[pt[i].i] = 0; flg[pt[i].i] = 0;
		mylink(S, pt[i].i, sqr(v[pt[i].i]-(mid+1))), mylink(pt[i].i, T, sqr(v[pt[i].i]-mid));
	}
	for(int i = el; i <= er; ++i) mylink(E[i].v, E[i].u, inf);
	maxflow(); dfs(S);
	int pL = pl, pR = pr;
	for(int i = pl; i <= pr; ++i)
		if(flg[pt[i].i]) tmppt[pL++] = pt[i];
		else tmppt[pR--] = pt[i];
	for(int i = pl; i <= pr; ++i) pt[i] = tmppt[i];
	
	int eL = el, eR = er;
	for(int i = el; i <= er; ++i)
		if(flg[E[i].u] && flg[E[i].v]) tmpE[eL++] = E[i];
		else if(!flg[E[i].u] && !flg[E[i].v])tmpE[eR--] = E[i];
	for(int i = el; i <= er; ++i) E[i] = tmpE[i];
	
	solve(vl, mid, pl, pL-1, el, eL-1);
	solve(mid+1, vr, pR+1, pr, eR+1, er);
}
int main () {
	freopen("shop.in", "r", stdin);
	freopen("shop.out", "w", stdout);
	read(n), read(m);
	int vmn = 1000000, vmx = 0;
	for(int i = 1; i <= n; ++i) read(c[i]), pt[i].i = i;
	for(int i = 1; i <= n; ++i) read(v[i]), vmn = min(vmn, v[i]), vmx = max(vmx, v[i]);
	for(int i = 1; i <= m; ++i)	read(a[i]), ina[a[i]] = 1;
	for(int i = 1; i <= m; ++i) read(b[i]), inb[b[i]] = 1;
	for(int i = 1; i <= m; ++i) {
		int x = a[i]; tmp.clear();
		for(int j = 1; j <= m; ++j)
			if(j != i) tmp.ins(c[a[j]]);
		for(int j = 1; j <= n; ++j)
			if(!ina[j] && tmp.mytry(c[j]))
				E[++tot] = (edge) { x, j };
	}
	for(int i = 1; i <= m; ++i) {
		int x = b[i]; tmp.clear();
		for(int j = 1; j <= m; ++j)
			if(j != i) tmp.ins(c[b[j]]);
		for(int j = 1; j <= n; ++j)
			if(!inb[j] && tmp.mytry(c[j]))
				E[++tot] = (edge) { j, x };
	}
	solve(vmn, vmx, 1, n, 1, tot);
	LL res = 0;
	for(int i = 1; i <= n; ++i) res += sqr(v[i]-ans[i]);
	printf("%lld\n", res);
}

D2T1

考试只会空间 O ( m 2 m ) O(m2^m) O(m2m)。然后发现可以优化。从小到大枚举 S S S其实相当于在遍历一个 D A G DAG DAG,可以用一个栈存一下从起点到当前 S S S的路径,然后枚举下一个 S ′ S' S就弹栈直到栈顶是 S ′ S' S的子集,这个时候栈顶和 S ′ S' S只会相差 l o w b i t ( S ′ ) lowbit(S') lowbit(S)。那么每个深度存两个 O ( m ) O(m) O(m)的数组表示 i i i到当前栈元素集合的出/入边。加入栈的时候直接从上一个深度的数组上继承过来然后加上 l o w b i t lowbit lowbit的贡献。

空间就是 O ( m 2 ) O(m^2) O(m2)的,时间还是 O ( 2 m m ) O(2^mm) O(2mm)

考试时只写了 m < = 21 m<=21 m<=21,下面是后来改的代码

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef unsigned long long ULL;
template<class T>inline void read(T &x) {
	char ch; int flg=1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
	for(x=ch-'0'; isdigit(ch=getchar()); x=x*10+ch-'0'); x *= flg;
}
const int MAXN = 23;
const int MAXS = 1<<23;
int n, m, k, E[MAXN][MAXN], in[MAXN], out[MAXN];
int sz[MAXS], Lg[MAXS], dp[MAXS];
inline void chkmin(int &x, int y) { y < x ? x = y : 0; }
int stk[MAXN+1], indx, f[MAXN+1][MAXN], g[MAXN+1][MAXN];
int main () {
	//freopen("transfer.in", "r", stdin);
	//freopen("transfer.out", "w", stdout);
	read(n), read(m), read(k);
	for(int i = 1, x, y = -1; i <= n; ++i) {
		read(x); --x;
		if((~y) && x != y) ++E[y][x], ++in[x], ++out[y];
		y = x;
	}
	int all = (1<<m)-1;
	memset(dp, 0x3f, sizeof dp); dp[0] = 0;
	stk[++indx] = 0; Lg[0] = -1;
	for(int s = 0; s < all; ++s) {
		sz[s] = sz[s>>1] + (s&1); int p = sz[s]+1;
		if(s) {
			Lg[s] = Lg[s>>1] + 1;
			while(indx && (stk[indx] | s) != s) --indx;
			stk[++indx] = s;
			for(int i = 0, lb = Lg[s&-s]; i < m; ++i)
				f[indx][i] = f[indx-1][i] + E[i][lb],
				g[indx][i] = g[indx-1][i] + E[lb][i];
		}
		for(int i = 0; i < m; ++i) if(!(s>>i&1))
			chkmin(dp[s^(1<<i)], dp[s] + (f[indx][i] + (in[i] - g[indx][i])) * k * p + (g[indx][i] - (out[i] - f[indx][i])) * p);
	}
	printf("%d\n", dp[all]);
}

D2T2

傻逼题。套路考过。考试时根本没想起来。思维僵化。直接退役。

本来考场应该能想出来,已经在分析 x − > x + 1 x->x+1 x>x+1的变化,按位考虑嫌麻烦没细想,其实很简单。

trie树所有值加一就从低到高建trie树,整体加一就是从根开始交换两个儿子,然后往交换后的0那一边递归。

改过了。

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef unsigned long long ULL;
template<class T>inline void read(T &x) {
	char ch; int flg=1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
	for(x=ch-'0'; isdigit(ch=getchar()); x=x*10+ch-'0'); x *= flg;
}
const int MAXN = 525050;
const int MAXM = MAXN * 40;
int n, val[MAXN], fa[MAXN], fir[MAXN], to[MAXN], nxt[MAXN], cnt;
inline void link(int u, int v) { to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; }
int s, rt[MAXN], tot, sz[MAXM], ch[MAXM][2], sum[MAXM];
long long ans;
void ins(int &x, int v, int d) {
	if(!x) x = ++tot; ++sz[x];
	if(d == 22) return;
	ins(ch[x][v>>d&1], v, d+1);
	sum[x] = sum[ch[x][0]] ^ sum[ch[x][1]] ^ ((sz[ch[x][1]]&1)<<d);
}
void mdf(int x, int d) {
	if(!x || d == 22) return;
	swap(ch[x][0], ch[x][1]); mdf(ch[x][0], d+1);
	sum[x] = sum[ch[x][0]] ^ sum[ch[x][1]] ^ ((sz[ch[x][1]]&1)<<d);
}
void merge(int &u, int v, int d) {
	if(!u || !v) { u = u + v; return; }
	sz[u] += sz[v];
	if(d == 22) return;
	merge(ch[u][0], ch[v][0], d+1);
	merge(ch[u][1], ch[v][1], d+1);
	sum[u] = sum[ch[u][0]] ^ sum[ch[u][1]] ^ ((sz[ch[u][1]]&1)<<d);
}
void dfs(int u) {
	for(int i = fir[u], v; i; i = nxt[i])
		dfs(v=to[i]), merge(rt[u], rt[v], 0);
	mdf(rt[u], 0);
	ins(rt[u], val[u], 0);
	ans += sum[rt[u]];
}
int main () {
	//freopen("tree.in", "r", stdin);
	//freopen("tree.out", "w", stdout);
	read(n);
	for(int i = 1; i <= n; ++i) read(val[i]);
	for(int i = 2; i <= n; ++i) read(fa[i]), link(fa[i], i);
	dfs(1);
	printf("%lld\n", ans);
}

D2T3

考试写了70。

O ( n 5 d ) O(n^5d) O(n5d)的做法考场上想到没写,结果居然能过。草。

下面写了 O ( n 4 d ) O(n^4d) O(n4d)的解法:

#include 
#include 
#include 
#include 
using namespace std;
#define pb push_back
const int mod = 998244353;
const int MAXN = 33;
const int MAXM = 450;
inline int qpow(int a, int b) {
	int re = 1;
	for(; b; b>>=1, a=1ll*a*a%mod)if(b&1)re=1ll*re*a%mod;
	return re;
}
int n, m;
struct edge { int u, v, w; }E[MAXM];
inline int upd(int x) { return x + (x >> 31 & mod); }
struct node {
	int a, b; //a + bx
	node(int a=0, int b=0):a(a), b(b){}
	inline node operator +(const node &o)const { return node(upd(a+o.a-mod), upd(b+o.b-mod)); }
	inline node operator -(const node &o)const { return node(upd(a-o.a), upd(b-o.b)); }
	inline node operator *(const node &o)const { return node(1ll*a*o.a%mod, (1ll*a*o.b+1ll*b*o.a)%mod); }
	inline node operator *(const int &o)const { return node(1ll*a*o%mod, 1ll*b*o%mod); }
}a[MAXN][MAXN];
int calcu() {
	node re(1, 0);
	for(int j = 1; j < n; ++j) {
		if(!a[j][j].a) {
			for(int i = j+1; i < n; ++i)
				if(a[i][j].a) { swap(a[i], a[j]); re = re * (mod-1); break; }
			if(!a[j][j].a && !a[j][j].b)
				for(int i = j+1; i < n; ++i)
					if(a[i][j].b) { swap(a[i], a[j]); re = re * (mod-1); break; }
		}
		if(!a[j][j].a && !a[j][j].b) return 0;
		re = re * a[j][j];
		if(a[j][j].a) {
			node iv = node(a[j][j].a, mod-a[j][j].b) * qpow(a[j][j].a, mod-3);
			for(int k = j; k < n; ++k) a[j][k] = a[j][k] * iv;
			for(int i = j+1; i < n; ++i) if(a[i][j].a || a[i][j].b)
				for(int k = n-1; k >= j; --k)
					a[i][k] = (a[i][k] - a[j][k] * a[i][j]);
		}
		else {
			node iv = node(qpow(a[j][j].b, mod-2), 0);
			for(int k = j; k < n; ++k) a[j][k] = a[j][k] * iv;
			for(int i = j+1; i < n; ++i) if(a[i][j].a || a[i][j].b)
				for(int k = n-1; k >= j; --k)
					a[i][k] = (a[i][k] - a[j][k] * a[i][j].b);
		}
	}
	return re.b;
}
const int MAXV = 152501+10;
int pr[MAXV], cnt_pr, phi[MAXV]; bool vis[MAXV];
vector<int>vec[MAXV];
void pre(int N) {
	phi[1] = 1;
	for(int i = 2; i <= N; ++i) {
		if(!vis[i]) phi[i] = i-1, pr[++cnt_pr] = i;
		for(int j = 1; j <= cnt_pr && i*pr[j] <= N; ++j) {
			vis[i*pr[j]] = 1;
			if(i % pr[j] == 0) { phi[i*pr[j]] = phi[i] * pr[j]; break; }
			phi[i*pr[j]] = phi[i] * (pr[j]-1);
		}
	}
}
int main () {
	//freopen("count.in", "r", stdin);
	//freopen("count.out", "w", stdout);
	scanf("%d%d", &n, &m); int mxv = 0;
	for(int i = 1; i <= m; ++i) {
		scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
		mxv = max(mxv, E[i].w);
		for(int j = 1; j*j <= E[i].w; ++j) if(E[i].w % j == 0) {
			vec[j].pb(i);
			if(E[i].w != j*j) vec[E[i].w/j].pb(i);
		}
	}
	pre(mxv);
	int ans = 0;
	for(int i = 1; i <= mxv; ++i) if((int)vec[i].size() >= n-1) {
		for(int j = 1; j < n; ++j)for(int k = 1; k < n; ++k)a[j][k] = 0;
		for(int j = vec[i].size()-1; j >= 0; --j) {
			node val = node(1, E[vec[i][j]].w); int u = E[vec[i][j]].u, v = E[vec[i][j]].v;
			a[u][u] = a[u][u] + val;
			a[v][v] = a[v][v] + val;
			a[u][v] = a[u][v] - val;
			a[v][u] = a[v][u] - val;
		}
		ans = (ans + 1ll * calcu() * phi[i]) % mod;
	}
	printf("%d\n", ans);
}

你可能感兴趣的:(2020 CQ省选退役记)