题目:
1. 中位数
【问题描述】
给定C个不同物品,每个物品有一重量和体积,保证每个物品的重量不一样。从中选出N个物品,在体积不超过F的情况下,使得选出的物品的重量的中位数最大。所谓中位数,就是排序后处在最中间的重量,比如3,8,9,7,5的中位数是7。
【输入格式】
第一行:三个用空格分开的整数:N,C和F。1 ≤ N ≤ 19999,N ≤ C ≤ 105
,0 ≤ F ≤ 2 × 109
第二行到C + 1行:每行有两个用空格分开的整数。第一个数是这个物品的重量Wi,第二个数是这个物品的体积Qi。
【输出格式】
第一行:一个整数,表示可以得到的最大中位数,如果F装不下任何N个物品,则输出-1。
【输入样例】
3 5 70
30 25
50 21
20 20
5 18
35 30
【输出样例】
35
【样例解释】
选择重量为 5, 35, 50 的物品,中位数为 35,体积18 + 30 + 21 = 69,小于70。
【数据范围】
40%的数据,1 ≤ N≤ C ≤200
100%的数据,1 ≤ N ≤ 19999,N ≤ C ≤ 105,0 ≤ F ≤ 2 × 109,0 ≤ Qi≤ 105,0 ≤ Wi≤ 2 × 109。保证n为奇数。
2. 爆炸
【问题描述】
有N个城市,M条双向道路组成的地图,城市标号为1到N。“西瓜炸弹”放在1号城市,保证城市1至少连接着一个其他城市。“西瓜炸弹”有P/Q的概率会爆炸,每次进入其它城市时,爆炸的概率相同。如果它没有爆炸,它会随机的选择一条道路到另一个城市去,对于当前城市所连接的每一条道路都有相同的可能性被选中。对于给定的地图,求每个城市“西瓜炸弹”爆炸的概率。
例如,假设只有两个城市1和2,它们被一条道路连接起来。最开始“西瓜炸弹”放在城市1,每次进入城市它都有1/2的可能性爆炸:
1 — 2
我们就有以下可能的路径(其中最后一项是结束城市,即“西瓜炸弹”爆炸并污染该城市):
1: 1
2: 1-2
3: 1-2-1
4: 1-2-1-2
5: 1-2-1-2-1
etc.
为了找出“西瓜炸弹”在城市1爆炸的可能性,我们可以把第1、3、5…种路径出现的概率加起来(在这个例子中即把所有奇数路径出现的可能性加起来)。
对于第k种路径出现的可能性为(1/2)^k:在经过前k-1次时,炸弹绝对不会在城市1爆炸(每一次的概率为1 – 1/2 = 1/2),然后最后在城市1爆炸(概率为1/2)。
因此,在城市1爆炸的可能性就是 1/2 + (1/2)^3 + (1/2)^5 + … ,把这些数都加起来就等于2 / 3,约为0.666666667。
所以在城市2爆炸的可能性就是1/3,约为0.333333333。
【输入格式】
第1行:四个被空格分隔整数:N,M,P和Q
第2..M+1行:第i行描述了两个空格分隔的整数:A_j 和 B_j(表示城市A_j与B_j相连)
【输出格式】
第1..N行:第i行为一个小数,表示第i个城市 “西瓜炸弹”爆炸的概率。至少要精确到10^-6才有效。
【输入样例1】
2 1 1 2
1 2
【输出样例1】
0.666666667
0.333333333
【输入样例2】
3 2 1 3
1 2
3 2
【输出样例2】
0.466666667
0.400000000
0.133333333
【数据范围】
20% 2<=N<=25 , 1<=M<=100
100% 2 <= N <= 300 ,1 <= M <= 44850 ,1 <= P <= 1,000,000,1 <= Q <= 1,000,000
3.序列划分
【题目描述】
给定一个序列{An},现在,需要把这个序列划分成K个子序列,使得每个子序列包含的数的个数不少于2,并且要么非升,要么非降。你的任务就是求出K的最小值。
【输入文件】
输入第一行一个正整数N,表示序列长度,接下来N行,第i行表示元素Ai-1。
【输出文件】
如果不能划分这个序列,输出一个数0;否则输出K。
【样例输入1】
6
12
33
97
18
15
33
【样例输出1】
2
【样例输入2】
1
88
【样例输出2】
0
【样例输入3】
4
77
22
22
11
【样例输出3】
1
【数据规模】
对于30%的数据,1<=N<=10;
对于100%的数据,1<=N<=25,1<=Ai<=100;
题解:
一:按照体积排序
1.预处理前i小、大的体积的物品的重量拿n/2个的最小重量
然后一个个枚举过去,看看是否成立
至于预处理就用一个堆好了
二:高斯消元+概率dp
本来想要简单的dp+收敛,没有想到数据那么坑。。。
(其实按照随机的概率大概可以过p/q>0.02的情况吧)
正解:高斯校园+概率
列出n个方程,解n个数字,就是高斯消元
三:迭代深搜
枚举有多少个可以,然后按照类似与导弹拦截的贪心方法做贪心
代码:
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; const int N=200005; int f[N],d[N],l,a[N],b[N],n,m,F; long long f1[N],f2[N]; void up(int x) { if (x==1)return; if (d[x]>d[x/2]) { swap(d[x],d[x/2]); up(x/2); } } void down(int x) { int i=x; if (x*2<=l&&d[x]<d[x*2])i=x*2; if (x*2<l&&d[i]<d[x*2+1])i=x*2+1; if (i!=x) { swap(d[x],d[i]); down(i); } } int cmp(int x,int y) { return a[x]<a[y]; } int main() { freopen("finance.in","r",stdin); freopen("finance.out","w",stdout); scanf("%d%d%d",&n,&m,&F); for (int i=1;i<=m;i++)scanf("%d%d",&a[i],&b[i]),f[i]=i; sort(f+1,f+m+1,cmp); for (int i=1;i<=n/2;i++)d[i]=b[f[i]],f1[i]=f1[i-1]+b[f[i]]; l=n/2; for (int i=1;i<=n/2;i++)up(i); for (int i=n/2+1;i<=m;i++) { if (b[f[i]]>=d[1]) { f1[i]=f1[i-1]; continue; } f1[i]=f1[i-1]+b[f[i]]-d[1]; d[1]=b[f[i]]; down(1); } memset(d,0,sizeof d); for (int i=m;i>m-n/2;i--)d[m-i+1]=b[f[i]],f2[i]=f2[i+1]+b[f[i]]; for (int i=1;i<=n/2;i++)up(i); for (int i=m-n/2;i;i--) { if (b[f[i]]>=d[1]) { f2[i]=f2[i+1]; continue; } f2[i]=f2[i+1]+b[f[i]]-d[1]; d[1]=b[f[i]]; down(1); } for (int i=m-n/2;i>n/2;i--) if (F>=f1[i-1]+f2[i+1]+b[f[i]]) { printf("%d",a[f[i]]); return 0; } puts("-1"); return 0; }
#include <bits/stdc++.h> using namespace std; typedef double ld; const int N=305; const ld eps=1e-15; int n,m,mp[N][N],du[N]; ld f[N][N],sum,P,Q; int main() { freopen("dotp.in","r",stdin); freopen("dotp.out","w",stdout); scanf("%d%d%lf%lf",&n,&m,&P,&Q); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); mp[x][y]++;mp[y][x]++; du[x]++;du[y]++; } f[1][n+1]=1; for(int i=1;i<=n;i++) { f[i][i]=1; for(int j=1;j<=n;j++) if(mp[i][j])f[i][j]+=((ld)P/Q-1)/du[j]*mp[i][j]; } for(int i=1;i<=n;i++) { int t=i; for(int j=i;j<=n;j++) if(fabs(f[j][i])>eps)t=j; for(int j=1;j<=n+1;j++)swap(f[i][j],f[t][j]); for(int j=1;j<=n;j++) if(j!=i&&fabs(f[j][i])>eps) { ld t=f[j][i]/f[i][i]; for(int k=1;k<=n+1;k++)f[j][k]-=f[i][k]*t; } } for(int i=1;i<=n;i++)sum+=(f[i][i]=f[i][n+1]/f[i][i]); for(int i=1;i<=n;i++)printf("%.9lf\n",(double)(f[i][i]/sum+eps)); return 0; }
#include<bits/stdc++.h> using namespace std; const int N=30; int a[N][N],b[N][N],A,B,ans[N],x[N],dep,n; void DFS(int u) { if (A+B>dep)return; if (u>n) { for (int i=1;i<=A;i++) if (*a[i]<2)return; for (int i=1;i<=B;i++) if (*b[i]<2)return; printf("%d\n",dep); exit(0); } int v=0; for (int i=1;i<=A;i++) if (a[i][*a[i]]<=x[u]&&(!v||a[v][*a[v]]<a[i][*a[i]]))v=i; if (!v) { ++A; a[A][++*a[A]]=x[u]; ans[u]=A; DFS(u+1); --*a[A--]; } else { a[v][++*a[v]]=x[u]; ans[u]=v; DFS(u+1); --*a[v]; } v=0; for (int i=1;i<=B;i++) if (b[i][*b[i]]>=x[u]&&(!v||b[v][*b[v]]>b[i][*b[i]]))v=i; if (!v) { ++B; b[B][++*b[B]]=x[u]; ans[u]=dep+1-B; DFS(u+1); --*b[B--]; } else { b[v][++*b[v]]=x[u]; ans[u]=dep+1-v; DFS(u+1); --*b[v]; } } int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++)scanf("%d",&x[i]); for (dep=1;dep*2<=n;dep++) { memset(a,0,sizeof a); memset(b,0,sizeof b); A=B=0; DFS(1); } puts("0"); return 0; }