联合省选是真的无聊
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=0∑nkixk(kn)=xidxd∑k=0nxk(kn)=xini(1+x)n−i
所以只需要将
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
vi≤vj也就连成了个有向图,然后背论文写个
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
0→2m−1中的点构成的
D
A
G
DAG
DAG上构成的
d
f
s
dfs
dfs树上的
d
p
dp
dp,我们从
0
0
0枚举到
2
m
−
1
2^m-1
2m−1实际上是在遍历一颗
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
n−1条边的时候做矩阵树定理。
所以复杂度是
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分