A - You're in the Army Now

贪心。我们直接将这些人按分数从大到小排序,然后按照这个顺序让他们选择,最后按照要求输出即可。但是输出的排序方式不是字典序,而是字母序,这里要注意。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<vector>
 5 #include<sstream>
 6 const int N=1e5+5;
 7 int n,m,k,a[N];
 8 std::string s[N];
 9 std::vector<std::string> g[N];
10 std::vector<int> e[N];
11 int t[N],b[N];
12 bool cmp(int x,int y) {
13     return b[x]>b[y];
14 }
15 bool cmp2(const std::string &a,const std::string &b) {
16     int len=std::min(a.length(),b.length());
17     int l,r;
18     for(int i=0;i<len;i++) {
19         if(a[i]==b[i]) continue;
20         if(a[i]==' '&&b[i]!=' ') return true;
21         if(a[i]!=' '&&b[i]==' ') return false;
22         if(a[i]>='a') l=a[i]-'a';
23         else l=a[i]-'A';
24         if(b[i]>='a') r=b[i]-'a';
25         else r=b[i]-'A';
26         if(l!=r) return l<r;
27         else return a[i]<b[i];
28     }
29     return a.length()<b.length();
30 }
31 int main() {
32     freopen("army.in","r",stdin);
33     freopen("army.out","w",stdout);
34     std::cin>>n>>m>>k;
35     for(int i=1;i<=m;i++) std::cin>>a[i];
36     std::string x;
37     std::getline(std::cin,x);
38     std::stringstream f;
39     for(int i=1;i<=n;i++) {
40         std::getline(std::cin,x);
41         int p=0;
42         for(int i=1;i<x.length();i++) {
43             if(x[i]>='0'&&x[i]<='9') {
44                 p=i;
45                 break;
46             }
47         }
48         s[i]=x.substr(0,p);
49         while(s[i].back()==' ') s[i].pop_back();
50         x=x.substr(p);
51         p=0;
52         while(s[i][p]==' ') p++;
53         s[i]=s[i].substr(p);
54         int k,z;f.clear();f<<x;
55         f>>b[i]>>k;
56         while(k--) {
57             f>>z;
58             e[i].push_back(z);
59         }
60         t[i]=i;
61     }
62     std::sort(t+1,t+1+n,cmp);
63     for(int i=1;i<=n;i++) {
64         int u=t[i];
65         for(int v:e[u]) {
66             if(a[v]>0) {
67                 --a[v];
68                 g[v].push_back(s[u]);
69                 break;
70             }
71         }
72     }
73     for(int i=1;i<=m;i++) {
74         if(i>1) printf("\n");
75         std::sort(g[i].begin(),g[i].end(),cmp2);
76         for(auto &w:g[i]) std::cout<<w<<std::endl;
77     }
78     return 0;
79 }
View Code

 

C - Ballistic

高斯消元。题目其实很明确,求解题目所述行列式即可。但是该行列式有未知数,我们无法方便的求解,但题目已经告诉我们,该多项式是个$n+1$次多项式,不妨我们用待定系数法,设该多项式为$f(\lambda)=\sum_{i=0}^na_i\lambda^{i}$,如果我们能分别计算出$\lambda=[1,n+1]$这个范围内的所有的值,那么我们就可以利用高斯消元求出这些系数。而求解一个特定的$\lambda$的值,也很容易,可以把值代入原行列式进行求解。当然,这都是理论方法,实际上,系数会特别大,所以需要大数,这里有个技巧,可以选取一些质数,让他们的乘积足够大,然后在这些质数的模意义下求行列式以及高斯消元,最后中国剩余定理合并。

  1 #include<iostream>
  2 #include<vector>
  3 #include<cstdio>
  4 #include<cassert>
  5 #include<cstring>
  6 typedef long long ll;
  7 
  8 struct BigInteger {
  9     typedef unsigned long long LL;
 10     static const int BASE = 100000000;
 11     static const int WIDTH = 8;
 12     std::vector<int> s;
 13 
 14     BigInteger& clean(){while(!s.back()&&s.size()>1)s.pop_back(); return *this;}
 15     BigInteger(LL num = 0) {*this = num;}
 16     BigInteger(std::string s) {*this = s;}
 17     BigInteger& operator = (long long num) {
 18         s.clear();
 19         do {
 20             s.push_back(num % BASE);
 21             num /= BASE;
 22         } while (num > 0);
 23         return *this;
 24     }
 25     BigInteger& operator = (const std::string& str) {
 26         s.clear();
 27         int x, len = (str.length() - 1) / WIDTH + 1;
 28         for (int i = 0; i < len; i++) {
 29             int end = str.length() - i*WIDTH;
 30             int start = std::max(0, end - WIDTH);
 31             sscanf(str.substr(start,end-start).c_str(), "%d", &x);
 32             s.push_back(x);
 33         }
 34         return (*this).clean();
 35     }
 36 
 37     BigInteger operator + (const BigInteger& b) const {
 38         BigInteger c; c.s.clear();
 39         for (int i = 0, g = 0; ; i++) {
 40             if (g == 0 && i >= s.size() && i >= b.s.size()) break;
 41             int x = g;
 42             if (i < s.size()) x += s[i];
 43             if (i < b.s.size()) x += b.s[i];
 44             c.s.push_back(x % BASE);
 45             g = x / BASE;
 46         }
 47         return c;
 48     }
 49     BigInteger operator - (const BigInteger& b) const {
 50         assert(b <= *this);
 51         BigInteger c; c.s.clear();
 52         for (int i = 0, g = 0; ; i++) {
 53             if (g == 0 && i >= s.size() && i >= b.s.size()) break;
 54             int x = s[i] + g;
 55             if (i < b.s.size()) x -= b.s[i];
 56             if (x < 0) {g = -1; x += BASE;} else g = 0;
 57             c.s.push_back(x);
 58         }
 59         return c.clean();
 60     }
 61     BigInteger operator * (const BigInteger& b) const {
 62         int i, j; LL g;
 63         std::vector<LL> v(s.size()+b.s.size(), 0);
 64         BigInteger c; c.s.clear();
 65         for(i=0;i<s.size();i++) for(j=0;j<b.s.size();j++) v[i+j]+=LL(s[i])*b.s[j];
 66         for (i = 0, g = 0; ; i++) {
 67             if (g ==0 && i >= v.size()) break;
 68             LL x = v[i] + g;
 69             c.s.push_back(x % BASE);
 70             g = x / BASE;
 71         }
 72         return c.clean();
 73     }
 74     BigInteger operator / (const BigInteger& b) const {
 75         assert(b > 0);
 76         BigInteger c = *this;
 77         BigInteger m;
 78         for (int i = s.size()-1; i >= 0; i--) {
 79             m = m*BASE + s[i];
 80             c.s[i] = bsearch(b, m);
 81             m -= b*c.s[i];
 82         }
 83         return c.clean();
 84     }
 85     BigInteger operator % (const BigInteger& b) const {
 86         BigInteger c = *this;
 87         BigInteger m;
 88         for (int i = s.size()-1; i >= 0; i--) {
 89             m = m*BASE + s[i];
 90             c.s[i] = bsearch(b, m);
 91             m -= b*c.s[i];
 92         }
 93         return m;
 94     }
 95 
 96     int bsearch(const BigInteger& b, const BigInteger& m) const{
 97         int L = 0, R = BASE-1, x;
 98         while (1) {
 99             x = (L+R)>>1;
100             if (b*x<=m) {if (b*(x+1)>m) return x; else L = x;}
101             else R = x;
102         }
103     }
104     BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this;}
105     BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this;}
106     BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this;}
107     BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this;}
108     BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this;}
109 
110     bool operator < (const BigInteger& b) const {
111         if (s.size() != b.s.size()) return s.size() < b.s.size();
112         for (int i = s.size()-1; i >= 0; i--)
113             if (s[i] != b.s[i]) return s[i] < b.s[i];
114         return false;
115     }
116     bool operator >(const BigInteger& b) const{return b < *this;}
117     bool operator<=(const BigInteger& b) const{return !(b < *this);}
118     bool operator>=(const BigInteger& b) const{return !(*this < b);}
119     bool operator!=(const BigInteger& b) const{return b < *this || *this < b;}
120     bool operator==(const BigInteger& b) const{return !(b < *this) && !(b > *this);}
121 };
122 
123 std::ostream& operator << (std::ostream& out, const BigInteger& x) {
124     out << x.s.back();
125     for (int i = x.s.size()-2; i >= 0; i--) {
126         char buf[20];
127         sprintf(buf, "%08d", x.s[i]);
128         for (int j = 0; j < strlen(buf); j++) out << buf[j];
129     }
130     return out;
131 }
132 
133 std::istream& operator >> (std::istream& in, BigInteger& x) {
134     std::string s;
135     if (!(in >> s)) return in;
136     x = s;
137     return in;
138 }
139 ll qpow(ll x,ll y,ll mod) {
140     ll res=1;
141     for(;y;y>>=1,x=x*x%mod) if(y&1) res=res*x%mod;
142     return res;
143 }
144 struct CRT {
145     const static int N=1e5+5;
146     std::vector<int> prime;
147     std::vector<int> inv;
148     bool vis[N];
149     int n;
150     BigInteger mod;
151     void init() {
152         for(int i=2;i<N;i++) if(!vis[i]) {
153             if(i>1e4) prime.push_back(i);
154             for(int j=i+i;j<N;j+=i) vis[j]=true;
155             if(prime.size()>=20) break;
156         }
157         n=prime.size();
158         inv.clear();
159         mod=1;
160         for(int i=0;i<n;i++) {
161             ll res=1;
162             mod*=prime[i];
163             for(int j=0;j<n;j++) if(i!=j) res=res*prime[j]%prime[i];
164             inv.push_back(int(qpow(res,prime[i]-2,prime[i])));
165         }
166         //std::cout<<mod<<std::endl;
167     }
168     BigInteger work(const std::vector<int> &g) {
169         BigInteger res=0;
170         for(int i=0;i<n;i++) {
171             res+=mod/prime[i]*inv[i]*g[i];
172             res%=mod;
173         }
174         return res;
175     }
176 }crt;
177 int solve(std::vector<std::vector<int> > a,int mod) {
178     int n=a.size();
179     int res=1;
180     for(int i=0;i<n;i++) for(int j=0;j<n;j++) a[i][j]=(a[i][j]%mod+mod)%mod;
181     for(int i=0;i<n;i++) {
182         int r=i;
183         for(;r<n&&!a[r][i];r++);
184         if(r==n) break;
185         if(r!=i) std::swap(a[r],a[i]),res=mod-res;
186         int inv=qpow(a[i][i],mod-2,mod);
187         for(int j=i+1;j<n;j++) {
188             int c=a[j][i]*inv%mod;
189             for(int k=i+1;k<n;k++) a[j][k]=(a[j][k]-c*a[i][k]%mod+mod)%mod;
190             a[j][i]=0;
191         }
192     }
193     for(int j=0;j<n;j++) res=res*a[j][j]%mod;
194     return res;
195 }
196 int main() {
197     freopen("ballistic.in","r",stdin);
198     freopen("ballistic.out","w",stdout);
199 
200     crt.init();
201     int n;scanf("%d",&n);
202     std::vector<std::vector<int> > a(n);
203     for(int i=0;i<n;i++) {
204         a[i].resize(n);
205         for(int j=0;j<n;j++) std::cin>>a[i][j];
206     }
207     std::vector<std::vector<int> > b(n+1),c;
208     for(int x=0;x<20;x++) {
209         std::vector<std::vector<int> > d;
210         int mod=crt.prime[x];
211         for(int j=1;j<=n+1;j++) {
212             c=a;std::vector<int> t;
213             for(int k=0;k<n;k++) c[k][k]-=j;
214             int now=1;
215             for(int k=0;k<=n;k++) {
216                 t.push_back(now);
217                 now=now*j%mod;
218             }
219             t.push_back(solve(c,mod));
220             d.push_back(t);
221         }
222         for(int i=0;i<=n;i++) {
223             int r=i;
224             for(;r<=n&&!d[r][i];r++);
225             std::swap(d[i],d[r]);
226             int inv=qpow(d[i][i],mod-2,mod);
227             for(int j=0;j<=n;j++) if(i!=j) {
228                 int c=d[j][i]*inv%mod;
229                 for(int k=i+1;k<=n+1;k++) d[j][k]=(d[j][k]-c*d[i][k]%mod+mod)%mod;
230                 d[j][i]=0;
231             }
232             for(int k=i+1;k<=n+1;k++) d[i][k]=d[i][k]*inv%mod;
233             d[i][i]=1;
234         }
235         for(int i=0;i<=n;i++) b[i].push_back(d[i][n+1]);
236     }
237     for(int i=n;~i;i--) {
238         BigInteger res=crt.work(b[i]);
239         if(res>crt.mod/2) {
240             std::cout<<'-'<<crt.mod-res<<std::endl;
241         }
242         else std::cout<<res<<std::endl;
243     }
244     return 0;
245 }
View Code

 

D-保卫萝卜4 

他给的凸包是不严格的,我们自己求一下凸包。

这个题数据出的非常垃圾。我们很容易想到对在哪个凸包里进行二分,然后O(这个凸包的点数)暴力判断,但这其实是一种假算法,可以轻松构造两个点数很多的严格凸包,这样复杂度近似mn。所以我觉得这个复杂度不可取。然而它能过。所以我觉得这个题目很垃圾。

另一种两个log的做法我认为才是正解。我们可以O(log凸包点数)来判断一个点是否在凸包内,其实这类似动态凸包的插点过程,我们每次在上下凸壳中找到x坐标大于等于询问点的第一个点,然后直接对这个点,前一个点,询问点 叉积判位置关系即可。

然而因为过于垃圾的数据,这两种做法在时间上竟然没有什么明显差异。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef double db;
 4 const db eps = 1e-6;
 5 int sign(db k){if(k>eps)return 1;else if(k<-eps)return -1;return 0;}
 6 int cmp(db k1,db k2){return sign(k1-k2);}
 7 int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}
 8 struct point{
 9     db x,y;
10     point operator + (const point &k1)const {return (point){k1.x+x,k1.y+y};}
11     point operator - (const point &k1)const {return (point){x-k1.x,y-k1.y};}
12     point operator * (db k1)const {return (point){x*k1,y*k1};}
13     point operator / (db k1)const {return (point){x/k1,y/k1};}
14     bool operator < (const point k1) const{
15         int a=cmp(x,k1.x);
16         if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
17     }
18 };
19 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
20 int inmid(point k1,point k2,point q){return inmid(k1.x,k2.x,q.x)&&inmid(k1.y,k2.y,q.y);}
21 int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;}
22 db area(vector<point> A){
23     db ans = 0 ;
24     for(int i=0;i<A.size();i++){//逆时针
25         ans+=cross(A[i],A[(i+1)%A.size()]);
26     }
27     return ans/2;
28 }
29 int contain(vector<point> A,point q){
30     int pd=0;A.push_back(A[0]);
31     for(int i=1;i<A.size();i++){
32         point u = A[i-1],v=A[i];
33         if(onS(u,v,q))return 1;if(cmp(u.y,v.y)>0)swap(u,v);
34         if(cmp(u.y,q.y)>=0||cmp(v.y,q.y)<0)continue;
35         if (sign(cross(u-v,q-v))<0) pd^=1;
36     }
37     return pd<<1;
38 }
39 vector<point> ConvexHull(vector<point>A,int flag=1){ // flag=0 不严格 flag=1 严格
40     int n=A.size(); vector<point>ans(n*2);
41     sort(A.begin(),A.end()); int now=-1;
42     for (int i=0;i<A.size();i++){
43         while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
44         ans[++now]=A[i];
45     } int pre=now;
46     for (int i=n-2;i>=0;i--){
47         while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
48         ans[++now]=A[i];
49     } ans.resize(now); return ans;
50 }
51 int T,n,m;
52 struct nmd{
53     vector<point> v;
54     db s;
55 }p[100005];
56 bool cmp2(nmd a,nmd b){
57     return a.s<b.s;
58 }
59 db S[100005];bool b[100005];
60 point t;
61 int main(){
62     freopen("castle.in","r",stdin);
63     freopen("castle.out","w",stdout);
64     scanf("%d",&T);
65     for(int i=1;i<=T;i++){
66         scanf("%d",&n);
67         for(int j=0;j<n;j++){
68             scanf("%lf%lf",&t.x,&t.y);
69             p[i].v.push_back(t);
70         }
71         p[i].v=ConvexHull(p[i].v,1);
72         p[i].s=abs(area(p[i].v));
73     }
74     sort(p+1,p+1+T,cmp2);
75     S[1]=p[1].s;
76     for(int i=2;i<=T;i++){
77         S[i]=p[i].s-p[i-1].s;
78     }
79     scanf("%d",&m);
80     while (m--){
81         scanf("%lf%lf",&t.x,&t.y);
82         int l=1,r=T;
83         while (l<=r){
84             int mid = l+r>>1;
85             if(contain(p[mid].v,t)){
86                 r=mid-1;
87             }else{
88                 l=mid+1;
89             }
90         }
91         b[l]=1;
92     }
93     db ans=0;
94     for(int i=1;i<=T;i++){
95         if(b[i])ans+=S[i];
96     }
97     printf("%.6f\n",ans);
98 }
暴力判断
  1 #include <cstdio>
  2 #include <vector>
  3 #include <algorithm>
  4 using namespace std;
  5 typedef double db;
  6 const db eps = 1e-6;
  7 inline int sign(db k){if(k>eps)return 1;else if(k<-eps)return -1;return 0;}
  8 inline int cmp(db k1,db k2){return sign(k1-k2);}
  9 struct point{
 10     db x,y;
 11     inline point operator + (const point &k1)const {return (point){k1.x+x,k1.y+y};}
 12     inline point operator - (const point &k1)const {return (point){x-k1.x,y-k1.y};}
 13     inline point operator * (db k1)const {return (point){x*k1,y*k1};}
 14     inline point operator / (db k1)const {return (point){x/k1,y/k1};}
 15     inline bool operator < (const point k1) const{
 16         int a=cmp(x,k1.x);
 17         if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
 18     }
 19 };
 20 inline db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
 21 inline db area(vector<point> A){
 22     db ans = 0 ;
 23     for(int i=0;i<A.size();i++){//逆时针
 24         ans+=cross(A[i],A[(i+1)%A.size()]);
 25     }
 26     return ans/2;
 27 }
 28 inline void getUDP(vector<point>A,vector<point>&U,vector<point>&D){
 29     db l=1e100,r=-1e100;
 30     for (int i=0;i<A.size();i++) l=min(l,A[i].x),r=max(r,A[i].x);
 31     int wherel,wherer;
 32     for (int i=0;i<A.size();i++) if (cmp(A[i].x,l)==0) wherel=i;
 33     for (int i=A.size();i;i--) if (cmp(A[i-1].x,r)==0) wherer=i-1;
 34     U.clear(); D.clear(); int now=wherel;
 35     while (1){D.push_back(A[now]); if (now==wherer) break; now++; if (now>=A.size()) now=0;}
 36     now=wherel;
 37     while (1){U.push_back(A[now]); if (now==wherer) break; now--; if (now<0) now=A.size()-1;}
 38 }
 39 inline bool checkup(vector<point> up,point p){
 40     int m = up.size();
 41     if(p.x<up[0].x||p.x>up[m-1].x)return false;//
 42     int id = lower_bound(up.begin(),up.end(),p)-up.begin();
 43     if(p.x==up[id].x){
 44         return p.y<up[id].y;
 45     }
 46     int pre = id-1;
 47     if(cross(up[id]-up[pre],p-up[pre])>0)return false;
 48     return true;
 49 }
 50 inline bool checkdown(vector<point>down,point p){
 51     int m = down.size();
 52     if(p.x<down[0].x||p.x>down[m-1].x)return false;
 53     int id = lower_bound(down.begin(),down.end(),p)-down.begin();
 54     if(p.x==down[id].x)return p.y<down[id].y;
 55     int pre = id-1;
 56     if(cross(down[id]-down[pre],p-down[pre])<0)return false;
 57     return true;
 58 }
 59 vector<point> ConvexHull(vector<point>A,int flag=1){ // flag=0 不严格 flag=1 严格
 60     int n=A.size(); vector<point>ans(n*2);
 61     sort(A.begin(),A.end()); int now=-1;
 62     for (int i=0;i<A.size();i++){
 63         while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
 64         ans[++now]=A[i];
 65     } int pre=now;
 66     for (int i=n-2;i>=0;i--){
 67         while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
 68         ans[++now]=A[i];
 69     } ans.resize(now); return ans;
 70 }
 71 int T,n,m;
 72 vector<point> v[100005],up[100005],down[100005];
 73 db s[100005];
 74 inline bool cmp2(int a,int b){
 75     return s[a]<s[b];
 76 }
 77 db S[100005];bool b[100005];
 78 int ind[100005];
 79 point t;
 80 int main(){
 81     freopen("castle.in","r",stdin);
 82     freopen("castle.out","w",stdout);
 83     scanf("%d",&T);
 84     for(int i=1;i<=T;i++){
 85         ind[i]=i;
 86         scanf("%d",&n);
 87         for(int j=0;j<n;j++){
 88             scanf("%lf%lf",&t.x,&t.y);
 89             v[i].push_back(t);
 90         }
 91         v[i]=ConvexHull(v[i],1);
 92         s[i]=abs(area(v[i]));
 93     }
 94     for(int i=1;i<=T;i++){
 95         getUDP(v[i],up[i],down[i]);
 96     }
 97     sort(ind+1,ind+1+T,cmp2);
 98     S[1]=s[ind[1]];
 99     for(int i=2;i<=T;i++){
100         S[i]=s[ind[i]]-s[ind[i-1]];
101     }
102     scanf("%d",&m);
103     db ans=0;
104     while (m--){
105         scanf("%lf%lf",&t.x,&t.y);
106         int l=1,r=T;
107         while (l<=r){
108             int mid = l+r>>1;
109             if(checkdown(down[ind[mid]],t)&&checkup(up[ind[mid]],t)){
110                 r=mid-1;
111             }else{
112                 l=mid+1;
113             }
114         }
115         if(!b[l])ans+=S[l];
116         b[l]=1;
117     }
118     printf("%.6f\n",ans);
119 }
二分判断

 

E - Creeping

状压$dp$。这题直接进行简单的状压$dp$即可,不过需要弄清楚规则,比方说对于打怪的机制,它是伤害和回复一起计算的,也就是说每秒钟掉的血量应该等于怪物的伤害值减去$Uther$的回复值,当然,该值可能为负数。然后还有另一个坑点,就是升级后,$Uther$的生命值也是会发生变化的,会增加两个等级之间最大生命值的差值,但是,这个可能为负数!换句话说,可能$Uther$打怪可以打死,但是升级后可能死亡!最后,题目有说$Uther$不介意打怪时长,故你可以认为它每次打新的怪物时都是满血的。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 const int N=22,M=105;
 5 int dp[1<<20],pre[1<<20];
 6 int n,k;
 7 int E[M],H[M],D[M],R[M];
 8 int h[N],d[N],e[N];
 9 int stk[N],top;
10 int main() {
11     freopen("creeping.in","r",stdin);
12     freopen("creeping.out","w",stdout);
13     scanf("%d%d",&n,&k);
14     for(int i=0;i<1<<n;i++) dp[i]=-1,pre[i]=-1;
15     for(int i=1;i<=k;i++) scanf("%d%d%d%d",E+i,H+i,D+i,R+i);
16     for(int i=0;i<n;i++) {
17         scanf("%d%d%d",h+i,d+i,e+i);
18     }
19     dp[0]=H[1];
20     int ans=0,mask=0;
21     for(int i=0;i<1<<n;i++) if(dp[i]>0) {
22         int tot=0;
23         for(int j=0;j<n;j++) if(i>>j&1) tot+=e[j];
24         int p=std::upper_bound(E+1,E+1+k,tot)-E-1;
25         for(int j=0;j<n;j++) if(!(i>>j&1)) {
26             long long t=(h[j]+D[p]-1)/D[p];
27             long long tmp=H[p]-t*(d[j]-R[p]);
28             if(tmp<=0) continue;
29             int rem=std::min(tmp,1LL*H[p]);
30             int now=tot+e[j];
31             int pp=std::upper_bound(E+1,E+1+k,now)-E-1;
32             rem+=H[pp]-H[p];
33             if(rem<=0) continue;
34             if(1>dp[i|1<<j]) {
35                 dp[i|1<<j]=1;
36                 pre[i|1<<j]=j;
37             }
38         }
39         if(tot>ans) {
40             ans=tot;
41             mask=i;
42         }
43     }
44     //printf("%d---\n",dp[2]);
45     printf("%d\n",ans);
46     top=0;
47     while(mask) {
48         stk[top++]=pre[mask];
49         mask=mask^1<<pre[mask];
50     }
51     printf("%d\n",top);
52     for(int i=top-1;~i;i--) printf("%d%c",stk[i]+1," \n"[i==0]);
53     return 0;
54 }
View Code

 

G - Princess

签到题。若公主斩断了$k-1$次头发,那么它的头发生长时间就可以分成$k$段,每一段的生长速度互不相同,设第$i$段的时长为$x_i$,则肯定有$\prod_{i=1}^{k}x_i=L$,换句话说,该问题等价于找一些数使得他们的乘积为$L$且和最小,假设我们分成$k$个数,那么,要使得和最小,这$k$个数肯定都是一样的,故,我们等价于求解$f(n)=n*L^{\frac{1}{n}}$的最小值,一个递增的函数乘一个递减的函数,因此我们断定它是一个凸函数,故我们可以三分。当然,还有另一种做法,可以发现,当$n$比较大时,$L^{\frac{1}{n}}$就比较小了,所以我们可以直接枚举一定数量的$n$,然后取最小值。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 long long L;
 5 double getAns(long long x) {
 6     return x*pow(L,1.0/x);
 7 }
 8 int main() {
 9     freopen("princess.in","r",stdin);
10     freopen("princess.out","w",stdout);
11     scanf("%lld",&L);
12     long long l=1,r=1e18,mid;
13     while(r-l>2) {
14         long long ll=l+(r-l)/3,rr=r-(r-l)/3;
15         if(getAns(ll)<=getAns(rr)) r=rr;
16         else l=ll;
17     }
18     double ans=L;
19     while(l<=r) {
20         ans=std::min(ans,getAns(l++));
21     }
22     printf("%.10f\n",ans);
23     return 0;
24 }
View Code

 

J - Orcish Transportation

网络流。这个题,由于图是对称的,故我们可以猜想,相互对应的两条边的流量是可以进行平均的,所以,我们直接跑最大流然后输出两条边的平均值。但是,这题流量为浮点数,且输出要求比较谜,它说需要尽可能的精确,注意到输入描述中说明了流量最多为包含四位小数,故我们可以化成整数,也就是都乘以$10^4$,最后答案再除以$10^4$即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxm=3e5+5;
 7 int n,m,f;
 8 const ll INF=1e17;
 9 bool vis[maxm];
10 struct node {
11     int to,nxt; ll cap;
12 }edge[maxm];int ecnt=0;
13 int q[maxm],l=0,r=0;// 数组模拟队列
14 int head[605],level[605],iter[605];
15 void init() {
16     for(int i=1;i<=2*n;i++) head[i]=-1;
17     ecnt=0;
18 }
19 void add(int from, int to, ll cap) {
20     int &i=ecnt;
21     edge[i].to=to;edge[i].cap=cap;edge[i].nxt=head[from];head[from]=i++;
22     edge[i].to=from;edge[i].cap=0;edge[i].nxt=head[to];head[to]=i++;
23 }
24 void bfs(int s) {
25     for(int i=1;i<=2*n;i++) level[i]=-1;
26     level[s]=0;
27     l=r=0;
28     q[r++]=s;
29     int x;
30     while(l<r) {
31         x=q[l++];
32         for(int i=head[x];i!=-1;i=edge[i].nxt) {
33             node& e=edge[i];
34             if(e.cap>0&&level[e.to]<0) {
35                 level[e.to]=level[x]+1;
36                 q[r++]=e.to;
37             }
38         }
39     }
40 }
41 ll dfs(int v, int t, ll f) {
42     if(v==t) return f;
43     for(int &i=iter[v];i!=-1;i=edge[i].nxt) {
44         node& e=edge[i];
45         if(e.cap>0&&level[v]<level[e.to]) {
46             ll d=dfs(e.to,t,min(f,e.cap));
47             if(d>0) {
48                 e.cap-=d;
49                 edge[i^1].cap+=d;
50                 return d;
51             }
52         }
53     }
54     return 0;
55 }
56 ll maxFlow(int s,int t) {
57     ll flow=0;
58     while(true) {
59         bfs(s);
60         if(level[t]<0) return flow;
61         for(int i=1;i<=2*n;i++) iter[i]=head[i];
62         ll f;
63         while((f=dfs(s,t,INF))>0)
64             flow+=f;
65     }
66 }
67 ll W[maxm];
68 int match[605];
69 int main(){
70     freopen("transportation.in","r",stdin);
71     freopen("transportation.out","w",stdout);
72     scanf("%d%d",&n,&m); int u, v; double w;
73     init();
74     for(int i=1;i<=n;i++) match[i]=i+n, match[i+n]=i;
75         char s[30];
76     for(int i=1;i<=m;i++){
77         scanf("%d%d%s",&u,&v,s); ll t=0;
78         int len=strlen(s),p=-1;
79         for(int i=0;i<len;i++) {
80             if(s[i]=='.') p=i;
81             else t=t*10+s[i]-'0';
82         }
83         if(p==-1) t*=10000;
84         else {
85             p=4-(len-p-1);
86             while(p--) t=t*10;
87         }
88         vis[ecnt]=1; W[ecnt]=t; add(u,v,t), add(match[v],match[u],t);
89     }
90     double ans=maxFlow(1,n+1);
91     printf("%.10f\n",ans*1.0/10000);
92     for(int i=0;i<ecnt;i++){
93         if(!vis[i]) continue;
94         double t=2*W[i]-edge[i].cap-edge[i+2].cap;
95         printf("%.10f\n",t*1.0/2/10000);
96     }
97     return 0;
98 }
View Code

 

posted on 2019-08-07 10:33  唯我心  阅读(177)  评论(0编辑  收藏  举报