CQOI 2020 无事可记

联合省选是真的无聊
D a y 0 Day0 Day0
复习了一堆 D a y 1 D a y 2 Day1Day2 Day1Day2都没考的知识点。
D a y 1 Day1 Day1

T1.冰火战士

线段树上二分即可。
写完之后才发现是最高温度,逼的我又写了个线段树二分,发现要跑6s,就懒得卡常了,出来发现自己还是跑的很快的
C o d e \mathcal Code Code

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
#define pb push_back
#define mp make_pair
#define Ct const
#define db double
#define maxn 2000006
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
	char ch;bool f=0;
	for(;!isdigit(ch=getc());) if(ch == '-') f = 1; 
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
	(f) && (res = -res);
}

int n;
int sb[maxn],sm[maxn<<2][2],pv[maxn][2],smh;
int data[maxn][4];
int sml , smr , pt;

#define lc u<<1
#define rc lc|1
void ins(int u,int l,int r,int p,int t,int v){
	sm[u][t] += v;
	if(l==r) return;
	int m = l+r>>1;
	p <= m ? ins(lc,l,m,p,t,v) : ins(rc,m+1,r,p,t,v);
}

void qry(int u,int l,int r,int v){
	if(l == r){
		pt = l;
		return;
	}
	int m = l+r>>1; 
	if(v + sm[lc][0] + sm[lc][1] - pv[m][1] >= 0) qry(lc,l,m,v);
	else smr -= sm[lc][1] , sml += sm[lc][0] , qry(rc,m+1,r,v + sm[lc][0] + sm[lc][1]);
}

int qry2(int u,int l,int r,int v){
	if(l == r) return l;
	int m = l+r>>1; 
	if(v - sm[rc][1] > 0) return qry2(lc,l,m,v-sm[rc][1]);
	return qry2(rc,m+1,r,v);
}

void print(int a){
	static int q[20]={};
	for(;a;a/=10) q[++q[0]] = a % 10;
	if(!q[0]) putchar('0');
	for(;q[0];) putchar('0' + q[q[0] --]);
}

int main(){
	read(n);
	rep(i,1,n){
		read(data[i][0]) , read(data[i][1]);
		if(data[i][0] == 1) read(data[i][2]) , read(data[i][3]) , sb[++sb[0]] = data[i][2];
	}
	sort(sb+1,sb+1+sb[0]);
	sb[0] = unique(sb+1,sb+1+sb[0]) - sb - 1;
	rep(i,1,n){
		if(data[i][0] == 1){
			int v = data[i][2] = lower_bound(sb+1,sb+1+sb[0],data[i][2])-sb , t = data[i][1];
			pv[v][t] += data[i][3];
			if(t) smh += data[i][3];
			ins(1,1,sb[0],v,t,data[i][3]);
		}
		else{
			int u = data[i][1] , v = data[u][2] , t = data[u][1];
			pv[v][t] -= data[u][3];
			if(t) smh -= data[u][3];
			ins(1,1,sb[0],v,t,-data[u][3]);
		}
		sml = 0 , smr = smh;
		qry(1,1,sb[0],-smh);
		int ans =max(smr,sml);
		if(!ans) puts("Peace");
		else{
			if(ans == smr){
				print(sb[qry2(1,1,sb[0],smr)]);
			} 
			else print(sb[pt-1]);
			putchar(' ');
			print(ans << 1);
			putchar('\n');
		}
	}	
}

T2 组合数问题

在考场上写了个垃圾的方log
∑ k = 0 n k i ‾ x k ( n k ) = x i d ∑ k = 0 n x k ( n k ) d x = x i n i ‾ ( 1 + x ) n − i \sum_{k=0}^n k^{\underline {i}}x^k\binom nk = x^i\frac {{\rm d}\sum_{k=0}^n x^k\binom nk}{{\rm d}x} = x^i n^{\underline i}(1+x)^{n-i} k=0nkixk(kn)=xidxdk=0nxk(kn)=xini(1+x)ni
所以只需要将 f ( k ) = ∑ i = 0 m a i k i f(k) = \sum_{i=0}^m a_ik^i f(k)=i=0maiki
转化为下降幂多项式 f ( k ) = ∑ i = 0 m c i k i ‾ f(k) = \sum_{i=0}^m c_ik^{\underline i} f(k)=i=0mciki
即可 O ( m log ⁡ n ) O(m\log n) O(mlogn)解决。
转化可以用斯特灵数实现无除法 O ( m 2 ) O(m^2) O(m2)
不知道为什么我需要除阶乘。
A C   C o d e \mathcal AC \ Code AC Code

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
#define pb push_back
#define mp make_pair
#define Ct const
#define pii pair<int,int>
#define db double
#define maxn 1005
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
	char ch;bool f=0;
	for(;!isdigit(ch=getc());) if(ch == '-') f = 1; 
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
	(f) && (res = -res);
}
int n,x,p,m,a[maxn],C[maxn][maxn],b[maxn],c[maxn];
int Pow(int b,int k,int mod){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod; return r; }
void exgcd(int a,int b,int &x,int &y,int &gcd){
	if(!b) x = 1 , y = 0 , gcd = a;
	else 
		exgcd(b,a%b,y,x,gcd),
		y-=(a/b)*x;
}

int INV(int x,int md){
	int a,b,c;
	exgcd(x,md,a,b,c);
	return a;
}

int Solve(int p,int md){
	rep(i,C[0][0]=1,m) rep(j,C[i][0]=1,i)
		C[i][j] = (C[i-1][j-1] + C[i-1][j]) % md;
	rep(i,0,m){
		c[i] = 0;
		per(j,m,0) c[i] = (1ll * c[i] * i + a[j]) % md;
	}
	rep(i,0,m){
		b[i] = 0;
		rep(j,0,i)
			b[i] = (b[i] + (i-j&1 ? -1ll : 1ll) * C[i][j] * c[j]) % md;
	}
	int rs=1,pw=0,ret=0;
	rep(i,0,m){
		int cc = 1ll * rs * Pow(p,pw,md) % md;
		ret = (ret + 1ll * Pow(x , i,md) * Pow(1+x,n-i,md) % md * b[i] % md * cc) % md;
		int v = n - i;
		for(;v && v % p == 0; v/= p) pw++;
		rs = 1ll * rs * v % md;
		v = i+1;
		for(;v && v % p == 0;v  /= p) pw--;
		rs = 1ll * rs * INV(v,md) % md;
	}
	return ret;
}

int main(){
	read(n),read(x),read(p),read(m);
	rep(i,0,m) read(a[i]);
	int X = p;
	int ans = 0 , md = 1;
	for(int i=2;i*i<=X;i++) if(X % i == 0){
		int pw = 1;
		for(;X % i == 0;X /= i) pw *= i; 
		int ret = Solve(i,pw);
		int x,y,gd;
		exgcd(md,pw,x,y,gd);
		x = 1ll * x * ((ret - ans) / gd) % (md * pw);
		ans = (1ll * x * md + ans) % (md * pw); 
		md *= pw;
	}
	if(X > 1){
		int pw = X;
		int ret = Solve(X,pw);
		int x,y,gd;
		exgcd(md,pw,x,y,gd);
		x = 1ll * x * ((ret - ans) / gd) % (md * pw);
		ans = (1ll * x * md + ans) % (md * pw); 
		md *= pw;
	}
	printf("%d\n",(ans+md)%md);
}

T3:魔法商店

发现两个符合条件的方案一定礼物个数都是一样的。
就硬猜我们只需要保证 A A A里面的一个礼品被其他礼品替换之后如果仍然符合条件,那么替换后的方案值一定要 ≥ \geq 原来的方案,因为 A A A中别的礼品都没换,所以就变成了两个礼品之间 v v v的大小关系, v i ≤ v j v_i \leq v_j vivj也就连成了个有向图,然后背论文写个 L 2 L_2 L2的保序回归即可。
C o d e Code Code

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define pb push_back
#define mp make_pair
#define Ct const
#define db double
#define pii pair<int,int>
#define inf 0x3f3f3f3f3f3f3f3fll
#define LL long long
#define maxn 1005
using namespace std;

int n,m,a[maxn],b[maxn],v[maxn],ina[maxn],inb[maxn];
int sz;
unsigned long long c[maxn];

unsigned long long ar[100];
void ins(unsigned long long x){
	for(int i=0;x && i<64;i++) if(x >> i & 1){
		if(ar[i]) x ^= ar[i];
		else ar[i] = x , sz++ , x = 0;
	}
}

#define maxm maxn * maxn
int buf[maxn],info[maxn],Prev[maxm],to[maxm],cnt_e=1,S,T;
LL cap[maxm],ans;
void Node(int u,int v,LL c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cap[cnt_e]=c; }
void Line(int u,int v,LL c){ Node(u,v,c),Node(v,u,0); }
LL sqr(LL a){ return a * a; }
int h[maxn];

bool BFS(vector<int>&A){
	static int q[maxn],L,R;
	rep(i,0,A.size()-1) info[A[i]] = buf[A[i]] , h[A[i]] = -1;
	info[S] = buf[S] , info[T] = buf[T];
	q[L=R=0] = T;h[S] = -1 , h[T] = 0;
	for(int u;L<=R;){
		u=q[L++];
		for(int i=info[u],v;i;i=Prev[i]){
			if(cap[i^1] && h[v=to[i]] == -1)
				h[v] = h[u] + 1, q[++R] = v; 
		}
	}
	return h[S] != -1;
}

LL aug(int u,LL mx){
	if(u == T) return mx;
	LL st = mx , inc;
	for(int &i=info[u],v;i;i=Prev[i]) if(cap[i] && h[v=to[i]] + 1 == h[u] && (inc = aug(v , min(cap[i] , st)))){
		st -= inc , cap[i] -= inc , cap[i^1] += inc;
		if(!st) return mx - st;
	}
	return mx - st;
}

int cl[maxn];
void Solve(int L,int R,vector<int>&A,vector<pii>&E){
	if(L == R){
		rep(i,0,A.size()-1) ans += sqr(v[A[i]] - L);
		return;
	}
	if(A.empty()) return;
	if(A.size() == 1){
		ans += sqr(max(L-v[A[0]] , max(v[A[0]]-R , 0)));
		return;
	}
	int mid = L+R >> 1;
	rep(i,0,E.size()-1) 
		Line(E[i].first , E[i].second , inf);
	rep(i,0,A.size()-1)
		if(v[A[i]] > mid) Line(S,A[i],sqr(mid-v[A[i]])-sqr(mid+1-v[A[i]]));
		else Line(A[i],T,sqr(mid+1-v[A[i]])-sqr(mid-v[A[i]]));
	rep(i,0,A.size()-1) buf[A[i]] = info[A[i]];
	buf[S] = info[S] , buf[T] = info[T];
	for(;BFS(A);) aug(S,inf);
	vector<int>ls,rs;
	rep(i,0,A.size()-1) 
		if(v[A[i]] > mid){
			if(h[A[i]] == -1) rs.pb(A[i]) , cl[A[i]] = 1;
			else ls.pb(A[i]) , cl[A[i]] = 0;
		}
		else{
			if(h[A[i]] == -1) rs.pb(A[i]) , cl[A[i]] = 1;
			else ls.pb(A[i]) , cl[A[i]] = 0;
		}
	vector<pair<int,int> >le,re;
	rep(i,0,E.size()-1)
		if(cl[E[i].first] == cl[E[i].second]){
			if(cl[E[i].first]) re.pb(E[i]);
			else le.pb(E[i]);
		}
	rep(i,0,A.size()-1) info[A[i]] = 0;
	cnt_e = 1;info[S] = info[T] = 0;
	Solve(L,mid,ls,le) , Solve(mid+1,R,rs,re);
}

int main(){
	
	freopen("shop.in","r",stdin);
	freopen("shop.out","w",stdout);
	
	scanf("%d%d",&n,&m);
	rep(i,1,n) cin >> c[i]; 
	int mx = 0 , mn = 0x3f3f3f3f;
	rep(i,1,n) scanf("%d",&v[i]) , mx = max(mx , v[i]) , mn = min(mn , v[i]);
	rep(i,1,m) scanf("%d",&a[i]),ina[a[i]] = 1;
	rep(i,1,m) scanf("%d",&b[i]),inb[b[i]] = 1;
	vector<pii >E;
	rep(i,1,m)
		rep(j,1,n){
			if(!ina[j]){
				sz = 0;
				memset(ar,0,sizeof ar);
				rep(k,1,m) if(k!=i) ins(c[a[k]]);
				ins(c[j]); 
				if(sz == m)
					E.pb(mp(a[i],j));
			}
			if(!inb[j]){
				sz = 0;
				memset(ar,0,sizeof ar);
				rep(k,1,m) if(k!=i) ins(c[b[k]]);
				ins(c[j]);
				if(sz == m)
					E.pb(mp(j,b[i]));
			}
		}
	S = n + 1 , T = n + 2;
	vector<int>p;
	rep(i,1,n) p.pb(i); 
	Solve(mn,mx,p,E);	
	cout << ans << endl;
}

希望Day1能够AK

D a y 2 Day2 Day2

T1.信号传递

状压 D P DP DP m 2 2 m m^22^m m22m显然。
考虑对于一个点 u u u在加入它的时候加入它的贡献。
发现 u u u的贡献可以分成下面几个部分:
p p p为当前位置, a u , v a_{u,v} au,v为从 u u u v v v的次数。
u u u前面的 v v v a v , u p + a u , v ( p + 1 ) k a_{v,u}p +a_{u,v}(p+1)k av,up+au,v(p+1)k
u u u后面的 v v v a u , v ( − p ) + a v , u ( p + 1 ) k a_{u,v}(-p)+a_{v,u}(p+1)k au,v(p)+av,u(p+1)k
所以就分别维护一下 f s t a , u f_{sta,u} fsta,u表示 s t a sta sta状态在 u u u前面的 a v , u a_{v,u} av,u总和之类的,
就可以 O ( m 2 m ) O(m2^m) O(m2m)
但是发现空间也是 O ( m 2 m ) O(m2^m) O(m2m)的。
发现这个 f f f d p dp dp,是在 0 → 2 m − 1 0 \rightarrow 2^m-1 02m1中的点构成的 D A G DAG DAG上构成的 d f s dfs dfs树上的 d p dp dp,我们从 0 0 0枚举到 2 m − 1 2^m-1 2m1实际上是在遍历一颗 d f s dfs dfs树,那么树上的转移就可以只记每一层的 f f f来卡空间。
具体实现看代码:
C o d e \mathcal Code Code

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define pb push_back
#define LL long long 
#define Ct const
#define db double
#define mp make_pair
#define maxn 23
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
	char ch;bool f=0;
	for(;!isdigit(ch=getc());) if(ch=='-') f=1;
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
	(f) && (res=-res);
}

int n,M,m,K,a[maxn][maxn],f[1<<maxn],bit[1<<maxn],lg[1<<maxn],sm[maxn];
int g[33][33] , h[33][33] , nb[33] , tp;

int main(){
	read(n),read(m),read(K);
	int pr;read(pr);pr--;
	rep(i,2,n){
		int x;read(x);x--;
		if(x ^ pr){
			a[pr][x]++;
			sm[pr]++ , sm[x] ++;
		}
		pr=x;
	}
	M = 1 << m;
	rep(i,0,m-1) lg[1 << i] = i;
	rep(i,0,M-1) bit[i] = bit[i>>1] + (i&1) , f[i] = 0x3f3f3f3f;
	rep(i,0,m-1)
		rep(j,0,m-1) if(i!=j) g[0][i] += a[i][j];
	nb[tp=0] = 0;
	f[0] = 0;
	rep(i,0,M-2){
		if(i){
			int sta = i - (i&-i) , v = lg[i&-i] , rsta = M-i-1 , cnt = 0;
			for(;(nb[tp]&i)!=nb[tp];tp--);
			for(int t,p;rsta;rsta-=t){
				t = rsta &- rsta;
				p = lg[t];
				int rp = cnt + (p >= v);
				
				g[tp+1][cnt] = g[tp][rp] - a[p][v];
				h[tp+1][cnt] = h[tp][rp] + a[v][p];
				cnt++;
			}
			nb[++tp] = i;
		}
		int rsta = M-i-1 , t , cnt = 0;
		for(;rsta;rsta-=t){
			t = rsta & -rsta;
			f[i|t] = min(f[i|t] , f[i] + g[tp][cnt] * (-bit[i]-1) + h[tp][cnt] * (bit[i]+1) + K * (bit[i] + 1) * (sm[lg[t]] - g[tp][cnt] - h[tp][cnt]));
			cnt++;
		}
	} 
	printf("%d\n",f[M-1]);  
}

T2:树

这很板啊。
01 t r i e 01trie 01trie合并+全局 + 1 +1 +1即可。
C o d e \mathcal Code Code

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define pb push_back
#define LL long long 
#define Ct const
#define db double
#define mp make_pair
#define maxn 1058576
#define maxp maxn * 25
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
	char ch;bool f=0;
	for(;!isdigit(ch=getc());) if(ch=='-') f=1;
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
	(f) && (res=-res);
}
int n,v[maxn],fa[maxn];
vector<int>G[maxn];
int rt[maxn],ch[maxp][2],sm[maxp],sz[maxp],tot;

void upd(int u,int d){
	if(!u) return;
	sm[u] = sm[ch[u][0]] ^ sm[ch[u][1]] ^ (sz[ch[u][1]] ? 1 << d : 0);
	sz[u] = sz[ch[u][0]] ^ sz[ch[u][1]];
}

void merge(int &u,int l,int r,int d){
	if(!l || !r) return (void)(u = l+r);
	u = l;
	if(!ch[l][0] && !ch[l][1]){
		sm[l] ^= sm[r];
		sz[l] ^= sz[r];
		return;
	}
	merge(ch[u][0],ch[l][0],ch[r][0],d+1),merge(ch[u][1],ch[l][1],ch[r][1],d+1);
	upd(u,d);
}

void add1(int u,int d){
	if(!u) return;
	swap(ch[u][0],ch[u][1]);
	add1(ch[u][0],d+1);
	upd(u,d);
}

void ins(int &u,int v,int d){
	if(!u) u = ++tot;
	if(d == 21) return (void)(sz[u] ^= 1);
	ins(ch[u][v>>d&1],v,d+1);
	upd(u,d);
}

LL ans;
void dfs(int u){
	rep(i,0,G[u].size()-1){
		int v = G[u][i];
		dfs(v);
		merge(rt[u] , rt[u] , rt[v] , 0);
	}
	add1(rt[u],0);
	ins(rt[u],v[u],0);
	ans += sm[rt[u]];
}

int main(){
	read(n);
	rep(i,1,n) read(v[i]);
	rep(i,2,n) read(fa[i]),G[fa[i]].pb(i);
	dfs(1);
	printf("%lld\n",ans);
}

T3:作业题

其实很sb一个题。
莫比乌斯反演,然后求边权和,把边权用 1 + w x 1+wx 1+wx表示最后求 [ x 1 ] [x^1] [x1]即可也就是可以   m o d   x 2 \bmod x^2 modx2来做到 O ( n 3 ) O(n^3) O(n3)矩阵树定理。
我们只在有至少 n − 1 n-1 n1条边的时候做矩阵树定理。
所以复杂度是 O ( n 3 m d n ) O(n^3 \frac {md}n) O(n3nmd),其中 d d d是因子个数,最多为一百多。
也就是 m = O ( n 2 ) m=O(n^2) m=O(n2) O ( n 4 d ) O(n^4d) O(n4d)勉强卡过实际上非常快,
快到 O ( n 5 d ) O(n^5d) O(n5d)我都不知道怎么卡。(就是枚举一条边删去然后跑矩阵树那种来求边权和。)

C o d e \mathcal Code Code

#include<bits/stdc++.h>
#define maxn 33
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define mod 998244353
#define Ct const
#define pb push_back
using namespace std;

int upd(int x){ return x += x >> 31 & mod; }
int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod; return r; }
struct data{
	int a,b;
	data(Ct int &a=0,Ct int &b=0):a(a),b(b){}
	data operator +(Ct data &B)Ct{ return data(upd(a+B.a-mod),upd(b+B.b-mod)); }
	data operator -(Ct data &B)Ct{ return data(upd(a-B.a),upd(b-B.b)); }
	data operator *(Ct data &B)Ct{ return data(1ll * a * B.a % mod , (1ll * b * B.a + 1ll * a * B.b) % mod); }
	data operator *(Ct int &B)Ct{ return data(1ll * a* B % mod , 1ll * b * B % mod); }
}a[maxn][maxn];

int n,m,sx[505],ty[505],cw[505];
#define maxv 160000
int phi[maxv],pr[maxv],cnt_pr,vis[maxv];
vector<int>G[160000];

int main(){
	scanf("%d%d",&n,&m);
	rep(i,1,m){
		scanf("%d%d%d",&sx[i],&ty[i],&cw[i]);
		for(int j=1;j*j<=cw[i];j++) if(cw[i] % j == 0){
			G[j].pb(i);
			if(cw[i] != j * j) G[cw[i] / j].pb(i);
		}
	}
	phi[1] = 1;
	for(int i=2;i<maxv;i++){
		if(!vis[i]) pr[cnt_pr++] = i , phi[i] = i-1;
		for(int j=0;pr[j] * i < maxv;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 ans = 0;bool flg = 0;
	rep(i,1,maxv-1) if(G[i].size() >= n-1){
		memset(a,0,sizeof a);
		rep(j,0,G[i].size()-1){
			int v = G[i][j] , x = sx[v] , y = ty[v] , w = cw[v];
			a[x][x] = (a[x][x] + data(1,w)) , a[y][y] = (a[y][y] + data(1,w));
			a[x][y] = (a[x][y] - data(1,w)) , a[y][x] = (a[y][x] - data(1,w));
		}
		data ret = data(1,0);
		rep(i,1,n-1){
			if(!a[i][i].a)
				rep(j,i+1,n-1) 
					if(a[j][i].a){
						swap(a[j],a[i]);
						ret.a = mod - ret.a;
						ret.b = mod - ret.b;
						break;
					}
			ret = ret * a[i][i];
			if(!a[i][i].a && !a[i][i].b){
				ret = data(0,0);
				break;
			}
			if(!a[i][i].a){
				flg = 1;
				data iv = data(Pow(a[i][i].b , mod-2),0);
				rep(j,i,n-1) a[i][j] = a[i][j] * iv;
				rep(j,i+1,n-1) if(a[j][i].a || a[j][i].b){
					data t = data(a[j][i].b,0);
					rep(k,i,n-1) a[j][k] = (a[j][k] - a[i][k] * t);
				}
			}
			else{
				data iv = data(a[i][i].a , mod-a[i][i].b) * Pow(a[i][i].a , mod-3);
				rep(j,i,n-1) a[i][j] = a[i][j] * iv;
				rep(j,i+1,n-1) if(a[j][i].a || a[j][i].b){
					data t = a[j][i];
					rep(k,i,n-1) a[j][k] = (a[j][k] - a[i][k] * t);
				}
			}
		}
		ans = (ans + 1ll * ret.b * phi[i]) % mod;
	}
	printf("%d\n",(ans+mod)%mod);
}

不知道要怎么翻盘啊,希望能得5分

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值