题目大意
有一个两面为空的硬币,正面和反面有区别。
你需要甩
k
k
次,每次其会有一面朝上,如果该面为空,你填一个整数上去,若不为空,获得该分数。
你希望最大化分数和为的概率。
做法
如果
s mod k=0
s
m
o
d
k
=
0
显然我们不管哪面都会填
s/k
s
/
k
,输出
2k
2
k
。
你能决定的是第一次摇到第2个面时,根据这是第几次决定另一面填啥。设这个为
y
y
,第一次填上去的就是,那么
x
x
是定值,你要提前准备。
下面我们令表示正面,
y
y
表示反面(实际上由于正反面有区别,答案要乘2)。
设有次出现正面。
那么要满足
Ax+(k−A)y=S
A
x
+
(
k
−
A
)
y
=
S
。
显然要有
(A,k−A)|S
(
A
,
k
−
A
)
|
S
即
(A,k)|S
(
A
,
k
)
|
S
。
我们可以证明,存在一个
x
x
,对于满足的
A
A
,都存在一个对应满足
Ax+(k−A)y=S
A
x
+
(
k
−
A
)
y
=
S
。
Ax+(k−A)y=S
A
x
+
(
k
−
A
)
y
=
S
。
(k−A)(y−x)=S−kx
(
k
−
A
)
(
y
−
x
)
=
S
−
k
x
。
由于
A
A
与对称可以得到
A|S−kx
A
|
S
−
k
x
。
所以有
lcm(A)|S−kx
l
c
m
(
A
)
|
S
−
k
x
。
令
lcm(A)∗p+kx=S
l
c
m
(
A
)
∗
p
+
k
x
=
S
。
我们知道一个简单的结论:
如果
(a,c)|d,(b,c)|d,那么有([a,b],c)|d
(
a
,
c
)
|
d
,
(
b
,
c
)
|
d
,
那
么
有
(
[
a
,
b
]
,
c
)
|
d
。这个结论的证明可以考虑从gcd以及lcm的本质出发,即对质因子次数取min与取max。
那么因为每个
A
A
都满足于是有
(lcm(A),k)|S
(
l
c
m
(
A
)
,
k
)
|
S
。
因此我们证明了这个
x
x
一定存在。
接下来就好做了,答案是
事实上这个
k
k
<script type="math/tex" id="MathJax-Element-4254">k</script>开到10^5当然也是能做的。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=60+10;
ll c[maxn][maxn];
int i,j,k,l,n,m,s;
ll ans,t;
class BearEmptyCoin{
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
public:
ll winProbability(int K,int S){
k=K;
s=S;
if (s%k==0){
ans=1;
fo(i,1,k) ans*=2;
return ans;
}
c[0][0]=1;
fo(i,1,k){
c[i][0]=1;
fo(j,1,i) c[i][j]=c[i-1][j]+c[i-1][j-1];
}
ans=0;
fo(j,1,k-1){
t=0;
fo(i,0,k-j-1)
if (s%gcd(i+j,k)==0) t=max(t,c[k-j-1][i]);
ans+=t;
}
return ans*2;
}
} zlt;
int main(){
printf("%lld\n",zlt.winProbability(2,-49));
}