Part.I 游记
今天真浮躁啊,明天就要回重庆了QAQ。。。
然后我们就不想做题了,我勉强写一下前两个题的题解吧,第三个题就只做一个题面展示好了。。。
Part.II 题解
A.投票
题目
题目描述
输入
输出
样例输入
Sample 1:
2 2
0.50 0.50
Sample 2:
4 2
0.00 0.00 1.00 1.00
Sample 3:
3 2
0.75 1.00 0.50
样例输出
Sample 1:
0.5
Sample 2:
1.0
Sample 3:
0.5
数据范围
样例解释
分析
先说一个毒瘤结论:将概率按从小到大的顺序排序后,我们取的人数是在前缀和后缀上的一段。
我也不会证明(如有会证明的请在评论区留言谢谢)
然后我们就跑DP就是了。
参考代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int Maxn=2000;
int N,K;
double P[Maxn+5];
double f_pre[Maxn+5][Maxn+5],f_suf[Maxn+5][Maxn+5];
int main() {
// #ifdef LOACL
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// #endif
freopen("vote.in","r",stdin);
freopen("vote.out","w",stdout);
scanf("%d %d",&N,&K);
for(int i=1;i<=N;i++)
scanf("%lf",&P[i]);
sort(P+1,P+N+1);
f_pre[0][0]=1;
for(int i=1;i<=K;i++)
for(int j=0;j<=i;j++) {
f_pre[i][j]=f_pre[i-1][j]*(1-P[i]);
if(j)f_pre[i][j]+=f_pre[i-1][j-1]*P[i];
}
reverse(P+1,P+N+1);
f_suf[0][0]=1;
for(int i=1;i<=K;i++)
for(int j=0;j<=i;j++) {
f_suf[i][j]=f_suf[i-1][j]*(1-P[i]);
if(j)f_suf[i][j]+=f_suf[i-1][j-1]*P[i];
}
double ans=0;
for(int i=0;i<=K;i++) {
double tmp=0;
for(int j=0;j<=K/2;j++)
tmp+=f_pre[i][j]*f_suf[K-i][K/2-j];
ans=max(ans,tmp);
}
printf("%.6f\n",ans);
return 0;
}
B.动态数点
题目
题目描述
输入
输出
样例输入
Sample 1:
5
4 6 9 3 6
Sampla 2:
30
15 15 3 30 9 30 27 11 5 15 20 10 25 20 30 15 30 15 25 5 10 20 7 7 16 2 7 7 28 7
样例输出
Sample 1:
1 3
2
Sample 2:
1 13
9
数据范围
分析
我们可设计一个 O ( N log 2 2 N ) O(N{\log_2}^2N) O(Nlog22N)的做法:
我们发现当一个区间所有数的GCD等于当前最小的数时,这个区间一定是“好”的。
那么我们可以用线段树维护区间GCD和最小值(也可以用ST表),然后枚举左端点,对每个左端点二分长度即可。
这里有一个 O ( N ) O(N) O(N)的做法:我们发现两个区间不相交时答案最好,所以我们就可以设计一个算法:对于一个位置 i i i,暴力找出以它为 a k a_k ak向右能找到的最远的地方 r i r_i ri,然后我们计算贡献,并将 i i i跳到 r i + 1 r_i+1 ri+1。
这个算法的正确性我暂时没有证明,若有证明可在评论区留言。
参考代码
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef unsigned int ui;
const int Maxn=500000;
int N;
ui A[Maxn+5];
bool vis[Maxn+5];
int main() {
// #ifdef LOACL
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// #endif
freopen("point.in","r",stdin);
freopen("point.out","w",stdout);
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d",&A[i]);s
vector<int> ans_pos;
int ans_max=0;
for(int i=1,l,r;i<=N;i=r+1) {
l=r=i;
while(l>1&&A[l-1]%A[i]==0)
l--;
while(r<N&&A[r+1]%A[i]==0)
r++;
if(r-l==ans_max)
ans_pos.push_back(l);
if(r-l>ans_max)
ans_max=r-l,ans_pos.clear(),ans_pos.push_back(l);
}
printf("%d %d\n",ans_pos.size(),ans_max);
for(int i=0;i<(int)ans_pos.size();i++)
printf("%d ",ans_pos[i]);
puts("");
return 0;
}
C.演员
题目
题目描述
输入
输出
样例输入
INPUT1
4 2
INPUT2
20 10
INPUT3
233 66
INPUT4
233333 23
样例输出
OUTPUT1
14
OUTPUT2
735074861
OUTPUT3
325609346
OUTPUT4
185055969