背景:
爆炸了。
T1 \text{T1} T1:
que \text{que} que:
给出
a
,
b
,
c
a,b,c
a,b,c,问能构造多少种方案的多项式使得
f
(
a
)
=
b
,
f
(
b
)
=
c
f(a)=b,f(b)=c
f(a)=b,f(b)=c。
sol \text{sol} sol:
很容易想到一种做法。
我们发现
x
x
x的系数不为
0
0
0的上限是
min
(
log
a
b
,
log
b
c
)
\min(\log_ab,\log_bc)
min(logab,logbc)。
考虑过后,我们发现这个并不大,直接搜索即可。
然后我因为没有判断无穷多解被卡到了
0
pts
0\text{pts}
0pts(多组数据)。
当然这不是正解。
首先我们就要判断无穷多解,即
a
=
b
=
c
=
1
a=b=c=1
a=b=c=1。
考虑
f
(
b
)
=
c
f(b)=c
f(b)=c,考虑将
c
c
c在
b
b
b进制下表示出来,由于系数小于
b
b
b(不然就可以向前进
1
1
1了),不能构成
b
b
b进制下的进位,因此此时的第
k
k
k位(定义从右往左数分别为
0
,
1
,
2
,
.
.
.
0,1,2,...
0,1,2,...位)就是
x
k
x^k
xk项的系数。最后带入
f
(
a
)
=
b
f(a)=b
f(a)=b中求解即可。
时间复杂度:
Θ
(
T
log
b
c
)
\Theta(T\log_bc)
Θ(Tlogbc)(
T
T
T表示数据组数)。
code \text{code} code:
这么水,就不贴了吧。
T2 \text{T2} T2:
que \text{que} que:
给定
a
,
b
,
c
,
d
a,b,c,d
a,b,c,d,求
gcd
(
a
F
n
+
b
F
n
+
1
,
c
F
n
+
d
F
n
+
1
)
\gcd(aF_n+bF_{n+1},cF_{n}+dF_{n+1})
gcd(aFn+bFn+1,cFn+dFn+1),其中
F
i
F_i
Fi表示斐波那契数列第
i
i
i项。
sol \text{sol} sol:
设
a
≤
c
a≤c
a≤c,若不满足,则
swap
\text{swap}
swap即可。
gcd
(
a
F
n
+
b
F
n
+
1
,
c
F
n
+
d
F
n
+
1
)
\gcd(aF_n+bF_{n+1},cF_{n}+dF_{n+1})
gcd(aFn+bFn+1,cFn+dFn+1)
带入更相减损术(后面的那一个式子减去
⌊
c
a
⌋
\lfloor\frac{c}{a}\rfloor
⌊ac⌋个前面的式子):
=
gcd
(
a
F
n
+
b
F
n
+
1
,
(
c
−
a
⌊
c
a
⌋
)
F
n
+
(
d
−
b
⌊
c
a
⌋
)
F
n
+
1
)
=\gcd(aF_n+bF_{n+1},(c-a\lfloor\frac{c}{a}\rfloor )F_n+(d-b\lfloor\frac{c}{a}\rfloor)F_{n+1})
=gcd(aFn+bFn+1,(c−a⌊ac⌋)Fn+(d−b⌊ac⌋)Fn+1)
= gcd ( a F n + b F n + 1 , ( c m o d    a ) F n + ( d − b ⌊ c a ⌋ ) F n + 1 ) =\gcd(aF_n+bF_{n+1},(c\mod a)F_n+(d-b\lfloor\frac{c}{a}\rfloor)F_{n+1}) =gcd(aFn+bFn+1,(cmoda)Fn+(d−b⌊ac⌋)Fn+1)
如此做
log
2
c
\log_2c
log2c次化简后得到:
=
gcd
(
a
F
n
+
b
F
n
+
1
,
c
F
n
+
1
)
=\gcd(aF_n+bF_{n+1},cF_{n+1})
=gcd(aFn+bFn+1,cFn+1)
如果
a
=
0
a=0
a=0或
c
=
0
c=0
c=0,特判掉即可。
先考虑求:
gcd
(
a
F
n
+
b
F
n
+
1
,
F
n
+
1
)
\gcd(aF_n+bF_{n+1},F_{n+1})
gcd(aFn+bFn+1,Fn+1)
考虑更相减损术,有:
=
gcd
(
a
F
n
,
F
n
+
1
)
=\gcd(aF_n,F_{n+1})
=gcd(aFn,Fn+1)
由于
F
n
⊥
F
n
+
1
F_{n}⊥F_{n+1}
Fn⊥Fn+1(互质),因此有:
=
gcd
(
a
,
F
n
+
1
)
=\gcd(a,F_{n+1})
=gcd(a,Fn+1)
考虑辗转相除法,有:
=
gcd
(
a
,
F
n
+
1
m
o
d
  
a
)
=\gcd(a,F_{n+1}\mod a)
=gcd(a,Fn+1moda)
用矩阵快速幂解决
F
n
+
1
m
o
d
  
a
F_{n+1}\mod a
Fn+1moda即可。
gcd
(
a
F
n
+
b
F
n
+
1
,
c
F
n
+
1
)
\gcd(aF_n+bF_{n+1},cF_{n+1})
gcd(aFn+bFn+1,cFn+1)
提取
g
=
gcd
(
a
F
n
+
b
F
n
+
1
,
c
F
n
+
1
)
g=\gcd(aF_n+bF_{n+1},cF_{n+1})
g=gcd(aFn+bFn+1,cFn+1),有:
=
g
⋅
gcd
(
(
a
F
n
+
b
F
n
+
1
)
/
g
,
c
(
F
n
+
1
/
g
)
)
=g\cdot\gcd\big((aF_n+bF_{n+1})/g,c(F_{n+1}/g)\big)
=g⋅gcd((aFn+bFn+1)/g,c(Fn+1/g))
可知此时
F
n
+
1
/
g
⊥
(
a
F
n
+
b
F
n
+
1
)
/
g
F_{n+1}/g⊥(aF_n+bF_{n+1})/g
Fn+1/g⊥(aFn+bFn+1)/g(两两互质),因此有:
=
g
⋅
gcd
(
(
a
F
n
+
b
F
n
+
1
)
/
g
,
c
)
=g\cdot\gcd\big((aF_n+bF_{n+1})/g,c\big)
=g⋅gcd((aFn+bFn+1)/g,c)
= gcd ( ( a F n + b F n + 1 ) , c g ) =\gcd\big((aF_n+bF_{n+1}),cg\big) =gcd((aFn+bFn+1),cg)
= gcd ( ( a F n + b F n + 1 ) , c g ) =\gcd\big((aF_n+bF_{n+1}),cg\big) =gcd((aFn+bFn+1),cg)
容易知道
c
g
<
a
F
n
+
b
F
n
+
1
cg<aF_n+bF_{n+1}
cg<aFn+bFn+1,带入辗转相除法,有:
=
gcd
(
(
a
F
n
+
b
F
n
+
1
)
m
o
d
  
(
c
g
)
,
c
g
)
=\gcd\big((aF_n+bF_{n+1})\mod (cg),cg\big)
=gcd((aFn+bFn+1)mod(cg),cg)
用矩阵快速幂解决
(
a
F
n
+
b
F
n
+
1
)
m
o
d
  
(
c
g
)
(aF_n+bF_{n+1})\mod (cg)
(aFn+bFn+1)mod(cg)即可。
code \text{code} code:
咕咕咕
...
\text{...}
...
T3 \text{T3} T3:
que \text{que} que:
原题传送门:
luogu P4643
\text{luogu P4643}
luogu P4643 [国家集训队]阿狸和桃子的游戏。
一幅图,
n
n
n个点,其中
{
n
∣
n
=
2
k
,
k
∈
N
+
}
\{n|n=2k,k∈N_{+}\}
{n∣n=2k,k∈N+}。每一轮你和对手轮流可以选择任意一个没有被染色的点染色,你染黑色,对手染白色。
每一个人的贡献是自己选的点的点权之和
+
+
+边权的贡献。对于边权贡献是,若连接一条边两个点颜色相同,则将这条边的权值加入对应颜色的人上。
可知最后你的贡献
−
-
−对手的贡献是固定的,求这个固定值。
sol \text{sol} sol:
很妙啊。
定义
v
a
l
val
val表示这条边的权值。
将边权划入到点权中。
如果两边都是⿊点,对答案的贡献为
1
∗
v
a
l
1*val
1∗val,可以看做两个⿊点分别为答案贡献了
1
2
∗
v
a
l
\frac{1}{2}*val
21∗val;
如果两边都是⽩点,对答案的贡献为
−
1
∗
v
a
l
-1*val
−1∗val,可以看做两个⽩点分别为答案贡献了
−
1
2
∗
v
a
l
-\frac{1}{2}*val
−21∗val;
如果⼀边是⽩点⼀边是⿊点,对答案的贡献为
0
0
0,可以看做⿊点为答案贡献了
1
2
∗
v
a
l
\frac{1}{2}*val
21∗val,⽩点为答案贡献了
−
1
2
∗
v
a
l
-\frac{1}{2}*val
−21∗val。
一种显然的博弈论知识是:对你新得到的点权降序,第奇数个的权值和为你的贡献;第偶数个的权值和为对手的贡献。
code \text{code} code:
update \text{update} update: 2019.8.8 2019.8.8 2019.8.8。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
double ans=0;
double a[10010];
bool cmp(double x,double y)
{
return x>y;
}
int main()
{
int x,y;
double z;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d %d %lf",&x,&y,&z);
a[x]+=z/2,a[y]+=z/2;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
ans+=a[i]*((i&1)?1:-1);
printf("%.0lf\n",ans);
}