zoukankan      html  css  js  c++  java
  • 20180225小测

    今天早晨一来就是一场猝不及防的考试(说好的下午考呢?)
    于是没有打卡(其实打了也是模拟赛爆零)

    T1:

    这题一看不可做啊......
    数据范围显然是nlogn,大概复杂度全都在排序。
    好,我们开始推结论什么的,一个人能感染到的人一定是前面比他快或者后面比他慢。
    然后呢?感染有时间顺序,所以我们能按照时间建图,存在点数O(n^3)的大力DP。
    but,多个人同时相遇怎么办?不会DP了,弃坑弃坑。
    写了10分爆搜然后写挂爆零了。
    关于这题正解?
    如果我们让时间趋于正无穷,那么这些人的顺序一定是按照速度排序的。
    考虑一个人能感染那些人?起始点在他前且速度比他快的,起始点在他后且比他慢的。
    那么,每个人在这个序列上能感染的区间就是[起始点比在他后的人且比他慢的中最慢的,起始点在他前的人且比他快的中最快的]。
    为什么?显然这个区间外的人都不能被感染(那些人一定是在前且慢或者在后且块)。
    对于区间内速度大于当前点的点,如果速度比右端点慢且在初始位置当前点右,那么他会被已经被感染的右端点感染。
    如果速度比左端点慢且初始位置在左,那么因为他比当前点快,一定会被当前点直接感染。
    左边情况同理。

    考场爆零代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 const int maxn=17;
     6 const double eps=1e-8;
     7 
     8 struct Node {
     9     double t;
    10     int u,v;
    11     Node() {}
    12     Node(double tt,int uu,int vv) { t = tt , u = uu , v = vv ; }
    13     friend bool operator < (const Node &a,const Node &b) {
    14         return a.t < b.t;
    15     }
    16 }ns[maxn*maxn];
    17 
    18 int x[maxn],v[maxn],used[maxn],vis[maxn],n,cnt,ans;
    19 
    20 inline void gnode(int a,int b) {
    21     if( x[a] < x[b] && v[a] < v[b] ) return;
    22     ns[++cnt] = Node((double)(x[b]-x[a])/(v[a]-v[b]),a,b);
    23 }
    24 inline void check() {
    25     memcpy(vis+1,used+1,sizeof(int)*n);
    26     for(int i=1,j,tp;i<=cnt;i=j+1) {
    27         j = i , tp = 0;
    28         while( j < cnt && std::fabs(ns[j+1].t-ns[i].t) <= eps ) ++j;
    29         for(int k=i;k<=j;k++) tp |= ( vis[ns[k].u] | vis[ns[k].v] );
    30         for(int k=i;k<=j;k++) vis[ns[k].u] |= tp , vis[ns[k].v] |= tp;
    31     }
    32     for(int i=1;i<=n;i++) if( !vis[i] ) return;
    33     ++ans;
    34 }
    35 inline void dfs(int pos) {
    36     if( pos > n ) return check();
    37     used[pos] = 0 , dfs( pos + 1 ) ,
    38     used[pos] = 1 , dfs( pos + 1 ) ;
    39 }
    40 
    41 int main() {
    42     scanf("%d",&n);
    43     for(int i=1;i<=n;i++) scanf("%d%d",x+i,v+i);
    44     for(int i=1;i<=n;i++)
    45         for(int j=i+1;j<=n;j++)
    46             gnode(i,j);
    47     std::sort(ns+1,ns+1+cnt);
    48     dfs(1);
    49     printf("%d
    ",ans);
    50     return 0;
    51 }
    View Code

    考后AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define lli long long int
     6 #define debug cout
     7 using namespace std;
     8 const int maxn=2e5+1e2;
     9 const int mod = 1e9 + 7;
    10 
    11 struct Person {
    12     int s,v,id;
    13     friend bool operator < (const Person &a,const Person &b) {
    14         return a.v < b.v;
    15     }
    16 }ns[maxn];
    17 
    18 
    19 struct Segment {
    20     int l,r;
    21     friend bool operator < (const Segment &a,const Segment &b) {
    22         return a.r != b.r ? a.r < b.r : a.l < b.l;
    23     }
    24 }ss[maxn];
    25 
    26 int mov[maxn];
    27 lli ff[maxn],sum[maxn],pows[maxn],*f;
    28 
    29 inline bool cmp(const Person &a,const Person &b) {
    30     return a.s < b.s;
    31 }
    32 
    33 int main() {
    34     static int n;
    35     scanf("%d",&n);
    36     for(int i=1;i<=n;i++) scanf("%d%d",&ns[i].s,&ns[i].v);
    37     sort(ns+1,ns+1+n,cmp);
    38     for(int i=1;i<=n;i++) ns[i].id = i;
    39     sort(ns+1,ns+1+n);
    40     for(int i=1;i<=n;i++) mov[ns[i].id] = i;
    41     sort(ns+1,ns+1+n,cmp);
    42     int m = 0;
    43     for(int i=1;i<=n;i++) {
    44         m = max( m , mov[i] );
    45         ss[i].r = m;
    46     }
    47     m = n+1;
    48     for(int i=n;i;i--) {
    49         m = min( m , mov[i] );
    50         ss[i].l = m;
    51     }
    52     sort(ss+1,ss+1+n);
    53     *pows = 1 , f = ff + 1;
    54     for(int i=1;i<=n;i++) pows[i] = pows[i-1] * 2 % mod;
    55     *f = *sum = 1;
    56     for(int i=1,l=1,r=1;i<=n;i++) {
    57         if( ss[l].r == i ) {
    58             r = l;
    59             while( r < n && ss[r+1].r == i ) ++r;
    60             for(int k=l;k<=r;k++) f[i] = ( f[i] + ( sum[i-1] - sum[ss[k].l-2] ) * pows[r-k] % mod ) % mod;
    61             l = r + 1;
    62         }
    63         sum[i] = ( sum[i-1] + f[i] ) % mod;
    64     }
    65     printf("%lld
    ",(f[n]+mod)%mod);
    66     return 0;
    67 }
    View Code


    T2:

    有一个奇怪的条件:存在药和药材的完美匹配。
    这是什么意思呢?就是当我们选择某种药的时候,必须选择其药材匹配的所有药。
    为什么呢?考虑当前你选出的集合,每个都匹配一种药材。如果你没有选择某个没有被匹配的药材对应的药,则这些药包含的药材多一种,不符合条件。
    所以一个二分图+一个最大权闭合子图就完了。

    考场AC代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=3e2+1e1,maxe=maxn*maxn;
      8 const int inf = 0x3f3f3f3f;
      9 
     10 int val[maxn],n,st,ed,ans;
     11 
     12 namespace Bingraph {
     13     int in[maxn][maxn],fa[maxn];
     14     bool vis[maxn];
     15     
     16     inline bool dfs(int pos) { // pos is left point which has value .
     17         for(int i=1;i<=n;i++) if( in[pos][i] && !vis[i] ) {
     18             vis[i] = 1;
     19             if( !fa[i] || dfs(fa[i]) ) {
     20                 fa[i] = pos;
     21                 return 1;
     22             }
     23         }
     24         return 0;
     25     }
     26     inline void pir() {
     27         for(int i=1;i<=n;i++) {
     28             memset(vis,0,sizeof(vis));
     29             dfs(i);
     30         }
     31     }
     32 }
     33 
     34 namespace Flow {
     35     int s[maxn],t[maxe<<2],nxt[maxe<<2],f[maxe<<2],dep[maxn];
     36     
     37     inline void coredge(int from,int to,int flow) {
     38         static int cnt = 1;
     39         t[++cnt] = to , f[cnt] = flow ,
     40         nxt[cnt] = s[from] , s[from] = cnt;
     41     }
     42     inline void singledge(int from,int to,int flow) {
     43         coredge(from,to,flow) , coredge(to,from,0);
     44     }
     45     inline bool bfs() {
     46         memset(dep,-1,sizeof(dep)) , dep[st] = 0;
     47         queue<int> q; q.push(st);
     48         while( q.size() ) {
     49             const int pos = q.front(); q.pop();
     50             for(int at=s[pos];at;at=nxt[at])
     51                 if( f[at] && !~dep[t[at]] )
     52                     dep[t[at]] = dep[pos] + 1 , q.push(t[at]);
     53         }
     54         return ~dep[ed];
     55     }
     56     inline int dfs(int pos,int flow) {
     57         if( pos == ed ) return flow;
     58         int ret = 0 , now = 0;
     59         for(int at=s[pos];at;at=nxt[at])
     60             if( f[at] && dep[t[at]] > dep[pos] ) {
     61                 now = dfs(t[at],min(flow,f[at]));
     62                 ret += now , flow -= now ,
     63                 f[at] -= now , f[at^1] += now;
     64                 if( !flow ) return ret;
     65             }
     66         if( !ret ) dep[pos] = -1;
     67         return ret;
     68     }
     69     inline int dinic() {
     70         int ret = 0 , now = 0;
     71         while( bfs() ) {
     72             while( now = dfs(st,inf) ) ret += now;
     73         }
     74         return ret;
     75     }
     76 }
     77 
     78 inline void build() {
     79     using namespace Flow;
     80     using namespace Bingraph;
     81     st = n + 1 , ed = st + 1;
     82     for(int i=1;i<=n;i++) val[i] = -val[i];
     83     for(int i=1;i<=n;i++) {
     84         if( val[i] > 0 ) {
     85             ans += val[i];
     86             singledge(st,i,val[i]);
     87         } else singledge(i,ed,-val[i]);
     88     }
     89     for(int i=1;i<=n;i++)
     90         for(int j=1;j<=n;j++)
     91             if( in[i][j] ) {
     92                 singledge(i,fa[j],inf);
     93             }
     94 }
     95 
     96 int main() {
     97     scanf("%d",&n);
     98     for(int i=1,t,x;i<=n;i++) {
     99         scanf("%d",&t);
    100         while( t-- ) {
    101             scanf("%d",&x);
    102             Bingraph::in[i][x] = 1;
    103         }
    104     }
    105     for(int i=1;i<=n;i++) scanf("%d",val+i);
    106     Bingraph::pir();
    107     build();
    108     ans -= Flow::dinic();
    109     printf("%d
    ",-ans);
    110     return 0;
    111 }
    View Code


    T3:

    看到n=1k换模数,直接就想NTT卷积了,然后发现不可做。
    输出样例和随机数,立下flag说如果能多过一个点就女装。
    然而一个点也没有多过。看来是天不让我女装(我也没办法是吧)。(不)
    我们枚举层数为奇数的点,考虑层数为奇数的点和层数为偶数的点构成一个二分图,然后这个二分图间可以随意连边,求这个完全二分图的生成树个数。
    这不是"BZOJ4766: 文艺计算姬"吗?直接n^(m-1)*m^(n-1)就好。
    证明可以用prufer序列证明,n左边点出现m-1次,m个右边点出现n-1次,乘法原理即可。
    别忘了因为我们钦定1号点为根,所以组合数是C(n-1,k-1)。

    考场5分代码:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 
     4 int main() {
     5     int n,k;
     6     scanf("%d%d",&n,&k);
     7     if( n == 4 && k == 2 ) puts("12");
     8     else {
     9         srand((unsigned long long)new char);
    10         printf("%d
    ",rand()%(n*n)+1);
    11     }
    12     return 0;
    13 }
    View Code

    考后AC代码:

     1 #include<cstdio>
     2 #define lli long long int
     3 
     4 lli n,k,mod,ans;
     5 
     6 inline lli fastpow(lli base,lli tim,lli mod) {
     7     lli now = base % mod , ret = 1;
     8     while( tim ) {
     9         if ( tim & 1 ) ret = ret * now % mod;
    10         if( tim >>= 1 ) now = now * now % mod;
    11     }
    12     return ret % mod;
    13 }
    14 inline lli c(lli n,lli m) {
    15     lli inv = 1 , ret = 1;
    16     for(lli i=n;i>n-m;i--) ret = ret * i % mod;
    17     for(lli i=1;i<=m;i++) inv = inv * i % mod;
    18     return ret * fastpow(inv,mod-2,mod) % mod;
    19 }
    20 
    21 int main() {
    22     scanf("%lld%lld%lld",&n,&k,&mod);
    23     ans = c(n-1,k-1) * fastpow(n-k,k-1,mod) % mod * fastpow(k,n-k-1,mod) % mod;
    24     printf("%lld
    ",ans);
    25     return 0;
    26 }
    View Code



    这次考试两个智商题一个不会,外加暴力写挂简直,果然还是我太弱了啊。
    真·爆零蒟蒻XZY

  • 相关阅读:
    HDU-1205
    HDU-2033
    HDU-2032
    HDU-2031
    HDU-2030
    HDU-2029
    HDU-2028
    HDU-2027
    HDU-2026
    HDU-2025
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8471065.html
Copyright © 2011-2022 走看看