zoukankan      html  css  js  c++  java
  • SDU暑期集训排位(5)题解

    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("
    ");
    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_ilambda^{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
    ",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
    ",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---
    ",dp[2]);
    45     printf("%d
    ",ans);
    46     top=0;
    47     while(mask) {
    48         stk[top++]=pre[mask];
    49         mask=mask^1<<pre[mask];
    50     }
    51     printf("%d
    ",top);
    52     for(int i=top-1;~i;i--) printf("%d%c",stk[i]+1," 
    "[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
    ",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
    ",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
    ",t*1.0/2/10000);
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    CentOS 配置自启动Redis
    WPF Popup全屏 弹出方法。解决只显示75%的问题。
    UpdatePanel控件的使用和局部刷新
    关于width与padding
    WPF 快捷方式
    深入浅出WPF——附加事件(Attached Event)
    控件属性使用代码动代绑定
    ICommand.CanExecuteChanged事件订阅对象的变化
    输入德文出现乱码现象的处理方法
    MVVM 模版里的控件怎样触发命令
  • 原文地址:https://www.cnblogs.com/Onlymyheart/p/11312404.html
Copyright © 2011-2022 走看看