Bzoj1181

Solution

分最大最小两种情况考虑

最大

直接加满,然后模拟

最小

肯定是把别人的加满。

好像直接求比较困难,考虑二分转化为判定性问题。

假设判定第 $x$ 个政党有 $t$ 个席位时是否可以。

令 $f[i][j]$ 表示前 $i$ 个政党控制 $j$ 个席位最少使用多少选票。然后有两个限制条件:

  • 至少有 5% 的票。(同时也告诉我们最多只有 $20$ 个政党)
  • $\dfrac{v_i}{k}>(or \ge )\dfrac{a_x}{t+1}$

然后转移一下就好。

另外,记得开够数组/ll

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define maxn 205
#define put() putchar('\n')
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
using namespace std;
inline void read(int &x){
int f=1;x=0;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
x*=f;
}
namespace Debug{
Tp void _debug(char* f,Ty t){cerr<<f<<'='<<t<<endl;}
Ts void _debug(char* f,Ty x,Ar... y){while(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
Tp ostream& operator<<(ostream& os,vector<Ty>& V){os<<"[";for(auto& vv:V) os<<vv<<",";os<<"]";return os;}
#define gdb(...) _debug((char*)#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
int v,n,m,rest;
int a[maxn],b[maxn];
struct node{
int id,b,num;
node(int a=0,int c=0,int d=0) {id=a;b=c;num=d;}
bool operator <(const node &x) const {
if (b*x.num!=num*x.b) return b*x.num<x.b*num;
return id>x.id;
}
}tr[205];
inline bool cmp(node x,node y) {
if (y.b*x.num!=y.num*x.b) return y.b*x.num<x.b*y.num;
return y.id>x.id;
}
priority_queue<node>q;
int d[maxn],f[25][205];
inline bool check(int id,int val) {
int i,j,k,tot=0;
for (i=1;i<=n;i++) if (i^id) tr[++tot]=(node){i,b[i],1};
sort(tr+1,tr+1+tot,cmp);tot=min(tot,19ll);
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for (i=1;i<=tot;i++) {
for (j=0;j<=m-val;j++) {
f[i][j]=f[i-1][j];
for (k=1;k<=j;k++) {
f[i][j]=min(f[i][j],f[i-1][j-k]+max(0ll,max((k*a[id]-(tr[i].id<id))/(val+1)+1,(v+19)/20)-tr[i].b));
}
}
}
return f[tot][m-val]<=rest;
}
signed main(void){
int i,j,k;
read(v);read(n);read(m);rest=v;
for (i=1;i<=n;i++) read(a[i]),rest-=a[i];
for (i=1;i<=n;i++) {
for (j=1;j<=n;j++) b[j]=a[j],d[j]=0;b[i]+=rest;
for (j=1;j<=n;j++) if (b[j]*20<v) b[j]=0;else q.push(node(j,b[j],1));
for (j=1;j<=m;j++) {
auto tmp=q.top();q.pop();
d[tmp.id]++;q.push(node(tmp.id,tmp.b,tmp.num+1));
}
printf("%lld ",d[i]);
while (!q.empty()) q.pop();
}
put();
// for (j=1;j<=n;j++) b[j]=a[j];cerr<<check(6,40);return 0;
// printf("%lld %lld\n",check(8,2),check(8,1));
for (j=1;j<=n;j++) b[j]=a[j];
for (i=1;i<=n;i++) {
if (a[i]*20<v) {printf("0 ");continue;}
int l=-1,r=m+1;
while (l+1<r) {
int mid=l+r>>1;
if (check(i,mid)) r=mid;
else l=mid;
}
printf("%lld ",r);
}
return 0;
}
/*
13 16 17 14 19 23 23 14 14 15 15 15 14 16
0 2 3 0 4 7 7 0 0 0 0 0 0 2
*/