zoukankan      html  css  js  c++  java
  • 2018年长沙理工大学第十三届程序设计竞赛 题解

    题目链接

    A - LL

    简单题。

    #include <bits/stdc++.h>
    using namespace std;
    
    int T;
    char s[2000];
    
    int main() {
      while(gets(s)) {
        int len = strlen(s);
        for(int i = 0; s[i]; i ++) {
          if(s[i] >= 'A' && s[i] <= 'Z') {
            s[i] = s[i] - 'A' + 'a';
          }
        }
        if(len != 8 || (strcmp("lovelive", s) != 0)) {
          printf("no
    ");
          
        }else {
          printf("yes
    ");
        }
      }
      return 0;
    }
    

    B - 奇怪的加法

    高精度加法一下,不要进位就好了。

    #include <bits/stdc++.h>
    using namespace std;
     
    char s[20];
    char t[20];
    char ans[20];
    int limit;
     
    int main() {
      while(~scanf("%s%s",s,t)) {
        limit = 20;
        int lens = strlen(s);
        int lent = strlen(t);
         
        for(int i = 0; i < lens / 2; i ++) {
          swap(s[i], s[lens - i - 1]);
        }
         
        for(int i = 0; i < lent / 2; i ++) {
          swap(t[i], t[lent - i - 1]);
        }
         
        //printf("%s %s
    ", s, t);
         
        for(int i = lens; i < limit; i ++) {
          s[i] = '0';
        }
         
        for(int i = lent; i < limit; i ++) {
          t[i] = '0';
        }
         
        for(int i = 0; i < limit; i ++) {
          int nums = s[i] - '0';
          int numt = t[i] - '0';
          ans[i] = (char)('0' + ((nums + numt) % 10));
        }
         
        int pos = 0;
         
        for(int i = 19; i >= 0; i --) {
          if(ans[i] != '0') {
            pos = i;
            break;
          }
        }
         
        for(int i = pos; i >= 0; i --) {
          printf("%c", ans[i]);
        }
        printf("
    ");
         
      }
      return 0;
    }
    

    C - 取手机

    总共排列方案有 ${ C }_{ a+b }^{ a }$ 种,第 $k$ 位是 b 手机的方案有 ${ C }_{ a+b-1 }^{ a }$ 种,因此概率为 $frac { { C }_{ a+b-1 }^{ a } }{ { C }_{ a+b }^{ a } } =frac { b }{ a+b } $。

    #include <bits/stdc++.h>
    using namespace std;
     
    int T;
     
    int main() {
       
      scanf("%d", &T);
      while(T --) {
        long long a, b, k;
        scanf("%lld%lld%lld", &a,&b,&k);
        printf("%.3f
    ", 1.0*b/(a+b));
      }
      return 0;
    }
    

    D - zzq的离散数学教室1

    $b=a imes prime$,因此枚举 $prime$,看有多少 $(a,b)$ 满足即可,算一下发现方案数是 $leftlfloor frac { R }{ prime }   ight floor -L+1$。

    这种做法的复杂度为 $O(P imes Q)$。其中 $P$ 为素数个数,$Q$ 为询问次数。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 1e6 + 10;
    int p[N], a[N], b[N];
    int ans[N],tt=0;
    int f[N];
    int t, u;
     
    void init(){
        t = 0, u = 0;
        for (int i = 2;i < N;i++) {
            if (a[i] == 0) p[t++] = i, a[i] = i;
            for (int j = 0;j < t && i * p[j] < N;j++) {
                a[i*p[j]] = p[j];
                if (i % p[j] == 0) {           
                    break;
                }
            }
        }
         
        //printf("%d
    ", t);
    }
     
    int main(){
        init();
        int L, R;
        while(~scanf("%d%d", &L, &R)) {
            int ans = 0;
            for(int i = 0; i < t; i ++) {
                if(L * p[i] > R) break;
                ans = ans + R / p[i] - L + 1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    

    这题询问出到 $10^5$ 次也可以搞。

    假设有一堆满足条件的二元组 $(a,b)$,对于一次询问 $(L, R)$,我们需要寻找有多少个二元组满足 $a$ 和 $b$ 均在 $[L,R]$ 内,这个就是很经典的问题了,离线很容易操作,要求在线的话就主席树。这里我们可以处理出所有满足条件的二元组,不会很多,因为 $b$ 的素因子个数就不多。

    类似的题目推荐:ZOJ 4008

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    int p[N], a[N], b[N];
    int ans[N],tt=0;
    int f[N];
    
    struct point{
    	int l,r,id;
    }x[N];
    
    int low(int x) {
    	return x&(-x);
    }
    
    void add(int x) {
    	for (int i = x;i<N;i+=low(i)) {
    		f[i]++;
    	}
    }
    
    int sum(int x) {
    	int res = 0;
    	for (int i = x;i > 0;i-=low(i)) {
    		res+=f[i];
    	}
    	return res;
    }
    
    void init(){
    	int t = 0, u = 0;
    	for (int i = 2;i < N;i++) {
    		if (a[i] == 0) p[t++] = i, a[i] = i;
    		for (int j = 0;j < t && i * p[j] < N;j++) {
    			a[i*p[j]] = p[j];
    			if (i % p[j] == 0) {
    				break;
    			}
    		}
    		int o = 0;
    		for (int j = i;j > 1;j /= a[j]) {
    			b[o++] = a[j];
    		}
    		sort(b,b+o);
    
    		o = unique(b,b+o) - b;
    		for (int j = 0;j<o;j++) {
    			add(i/b[j]);
    			//cout << "debug " << i / b[j] << endl;
    		}
    
    		for (;u<tt && x[u].r <= i;u++) {
    			if (x[u].l >= x[u].r) ans[x[u].id] = 0;
    			else {
    				ans[x[u].id] = sum(x[u].r) - sum(x[u].l - 1);
    			}
    		}
    		if (u==tt) break;
    	}
    }
    
    bool cmp(point a,point b) {
    	return a.r < b.r;
    }
    
    int main(){
    #ifdef ZHOUZHENTAO
    	freopen("test.in", "r", stdin);
    #endif
    	while (~scanf("%d%d",&x[tt].l,&x[tt].r)){
    		x[tt].id = tt;
    		tt ++;
    	}
    	sort(x,x+tt,cmp);
    	init();
    	for (int i = 0;i < tt;i++) {
    		printf("%d
    ",ans[i]);
    	}
    
    	return 0;
    }
    

    E - 小木乃伊到我家

    最短路。一开始忘记优先队列是大的排在前面了,果然是智力有缺陷。

    #include <bits/stdc++.h>
    using namespace std;
      
    const int maxn = 4e5 + 10;
     long long INF = 1e9;
    int T;
    int n, m;
    int sz, h[maxn], nx[maxn], to[maxn];
    long long val[maxn];
      
    long long dis[maxn];
      
    void add(int x, int y, long long z) {
      to[sz] = y;
      val[sz] = z;
      nx[sz] = h[x];
      h[x] = sz ++;
    }
      
    int main() {
        
      INF = INF * INF;
        
      scanf("%d%d", &n, &m);
      for(int i = 1; i <= n; i ++) {
        h[i] = -1;
        dis[i] = INF;
      }
        
      for(int i = 1; i <= m; i ++) {
        int u, v;
        long long w;
        scanf("%d%d%lld", &u, &v, &w);
        add(u, v, w);
        add(v, u, w);
      }
        
      priority_queue<pair<long long, int> > q;
        
      q.push(make_pair(0, 1));
      dis[1] = 0;
        
      while(!q.empty()) {
        pair<long long, int> pi = q.top();
        q.pop();
          
        if(dis[pi.second] < -pi.first) continue;
          
        for(int i = h[pi.second]; i!=-1;i=nx[i]) {
          if(dis[pi.second] + val[i] < dis[to[i]]) {
            dis[to[i]] = dis[pi.second] + val[i];
            q.push(make_pair(-dis[to[i]], to[i]));
          }
        }
          
      }
        
      if(dis[n] == INF) {
        printf("qwb baka
    ");
      } else {
        printf("%lld
    ", dis[n]);
      }
        
        
      return 0;
    }
    

    F - 箱庭的股市

    仔细观察一下可以发现就是求杨辉三角某一行的前缀和。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    int m,x,y,p;
    int f[N], g[N], inv[N];
     
    int main(){
        f[0] = g[0] = f[1] = g[1] = inv[1] = 1;
        for (int i = 2;i<N;i++) {
            f[i] = 1LL * f[i-1] * i % mod;
            inv[i] = 1LL * inv[mod % i] * (mod - mod /i) % mod;
            g[i] = 1LL * g[i-1] * inv[i] % mod;
        }
        while (~scanf("%d%d%d%d",&m,&x,&y,&p)) {
            int ans = 0;
            if (x==1||y==0) {
                printf("%d
    ", p);
                continue;
            }
            x = x - 1;
            for (int i = 0;i<= min(y,x);i++) {
                ans = (ans + 1LL * f[x] * g[i] % mod * g[x-i] % mod) % mod;
            }
            ans = 1LL * p * ans % mod;
            printf("%d
    ",ans);
        }
    }
    

    G - 逃离迷宫

    吐槽:题目里说:“现在你需要花费最少的时间拿到钥匙然后从迷宫的出口出去”。我一开始理解为首先是要求到钥匙的时间最少,然后从最少时间的钥匙那里挑一个走到出口,结果答案错误,后来改成整体最少时间就 AC 了。这个我感觉确实会引起歧义啊。

    #include <bits/stdc++.h>
    using namespace std;
     
    int INF = 10000000;
    const int maxn = 550;
    int T;
    int n, m;
    char s[maxn][maxn];
     
    int sx, sy;
    int ex, ey;
     
    int dis[2][maxn][maxn];
     
    int dir[4][2] = {
      {-1, 0},
      {1, 0},
      {0, -1},
      {0, 1}
    };
     
    int out(int x, int y) {
      if(x < 0 || x >= n) return 1;
      if(y < 0 || y >= m) return 1;
      return 0;
    }
     
    void bfs(int flag) {
      queue<int> q;
      if(flag == 0) {
        dis[flag][sx][sy] = 0;
        q.push(sx * m + sy);
      } else {
        dis[flag][ex][ey] = 0;
        q.push(ex * m + ey);
      }
       
      while(!q.empty()) {
        int st = q.front();
        q.pop();
         
        int nx = st / m;
        int ny = st % m;
         
        for(int i = 0; i < 4; i ++) {
          int tx = nx + dir[i][0];
          int ty = ny + dir[i][1];
          if(out(tx, ty)) continue;
          if(s[tx][ty] == '#') continue;
          if(flag == 0 && s[tx][ty] == 'E') continue;
          if(dis[flag][nx][ny] + 1 < dis[flag][tx][ty]) {
            dis[flag][tx][ty] = dis[flag][nx][ny] + 1;
            q.push(tx * m + ty);
          }
        }
      }
    }
     
    int main() {
      scanf("%d", &T);
      while(T --) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i ++) {
          scanf("%s", s[i]);
        }
        for(int i = 0; i < n; i ++) {
          for(int j = 0; j < m; j ++) {
            if(s[i][j] == 'P') sx = i, sy = j;
            else if(s[i][j] == 'E') ex = i, ey = j;
            dis[0][i][j] = dis[1][i][j] = INF;
          }
        }
         
        bfs(0);
        bfs(1);
         
        int ans = INF;
        
     
        for(int i = 0; i < n; i ++) {
          for(int j = 0; j < m; j ++) {
            if(s[i][j] != 'K') continue;
            if(dis[0][i][j] == INF) continue;
            if(dis[1][i][j] == INF) continue;
            ans = min(ans, dis[0][i][j] + dis[1][i][j]);
          }
        }
         
        if(ans == INF) {
          printf("No solution
    ");
          continue;
        }
         
        printf("%d
    ", ans);
      }
      return 0;
    }
    

    H - 数学考试

    枚举分割线,然后左边最大值和右边最大值加一加更新答案。左右两边最大值 dp 一下就能算出来了。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 2e5 + 10;
    long long INF = 1e9;
     
    int T, n, k;
    long long a[maxn];
    long long L[maxn], R[maxn];
     
    int main() {
      INF = INF * INF;
       
      scanf("%d", &T);
      while(T --) {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i ++) {
          scanf("%lld", &a[i]);
        }
         
        long long sum = 0;
        for(int i = 1; i <= k; i ++) {
          sum = sum + a[i];
        }
        L[k] = sum;
        for(int i = k + 1; i <= n; i ++) {
          sum = sum - a[i - k] + a[i];
          L[i] = max(L[i - 1], sum);
        //  cout << sum << endl;
        }
         
        sum = 0;
        for(int i = n; i >= n - k + 1; i --) {
          sum = sum + a[i];
        }
        R[n - k + 1] = sum;
        for(int i = n - k; i >= 1; i --) {
          sum = sum - a[i + k] + a[i];
          R[i] = max(R[i + 1], sum);
        //  cout << sum << endl;
        }
         
        long long ans = L[k] + R[k + 1];
         
        for(int i = k; i + k <= n; i ++) {
          // [, i], [i + 1, i + k]
          ans = max(ans, L[i] + R[i + 1]);
        //  cout << L[i] << " " << R[i + 1] << endl;
        }
         
        printf("%lld
    ", ans);
         
         
      }
      return 0;
    }
    

    I - 连续区间的最大公约数

    以每一个位置 $i$ 作为区间右端点,左端点从 $[1, i]$ 移动的过程中,区间 gcd 的种类不会超过 $log(n)$ 种,我们可以把这些处理出来,记录成四元组 $left( { L }_{ 1 },L_{ 2 },R,g ight) $,表示区间左端点在 $[L_1,L_2]$,右端点在 $R$ 的所有区间,最大公约数均为 $g$。

    所有的四元组已经 cover 了所有的子区间。那么对于每一次的询问 $(L, R, g)$,我们只需在和这一次询问拥有相同 $g$ 的四元组中寻找答案,去计算每一个四元组做出的贡献。

    例如询问为 $(4, 7, 3)$,四元组 $(1, 3, 3, 3)$ 的贡献为 0,虽然 $g$ 均为 3,但是无相交部分。四元组 $(2, 5, 6, 3)$ 的贡献为 2。虽然以 6 为结尾的有 4 个区间 $g$ 为 3,但是只有 2 个在询问的区间内。

    一种效率较高的做法如下:

    把询问离线,询问中 $g$ 相同的归为一类,去 gcd 为 $g$ 的四元组中计算答案。也就是按 $g$ 分类来计算。

    下面只考虑相同 $g$ 情况下的询问和四元组之间如何计算答案。

    对于一次询问 $(L, R, g)$,就是求 $R$ 小于等于询问的 $R$ 的四元组 $[L_1,L_2]$ 和 $[L, R]$ 交集长度之和。每次暴力求的话,复杂度为 $O(n^2)$,事实上可以按 $R$ 排序,然后利用线段树区间修改、求区间和来搞。 

    /*******************************
        Judge Result : AC
     *******************************/
     
    #include <bits/stdc++.h>
    #define rep(i,j,k) for (int i = j; i <= k; i++)
    #define per(i,j,k) for (int i = j; i >= k; i--)
    #define loop(i,j,k) for (int i = j;i != -1; i = k[i])
    #define lson x << 1, l, mid
    #define rson x << 1 | 1, mid + 1, r
    #define ff first
    #define ss second
    #define mp(i,j) make_pair(i,j)
    #define pb push_back
    #define pii pair<int,LL>
    #define in(x) scanf("%d", &x);
    using namespace std;
    typedef long long LL;
    const int low(int x) { return x&-x; }
    const double eps = 1e-4;
    const int INF = 0x7FFFFFFF;
    const int N = 4e5 + 10;
    int T, n, m, l, r;
    int g[N],d[N];
     
    long long s[N], k[N];
     
    int gcd(int x, int y) {
        return x%y ? gcd(y, x%y) : y;
    }
     
    void build(int x,int l,int r) {
        if (l == r) {
            scanf("%d",&g[x]);
            d[r] = g[x];
        }
        else {
            int mid = l + r >> 1;
            build(lson);
            build(rson);
            g[x] = gcd(g[x<<1], g[x<<1|1]);
        }
    }
     
    int query(int x,int l,int r,int ll,int rr) {
        if (ll<=l && r<=rr) return g[x];
        int mid = l + r>>1;
        if (rr <= mid) return query(lson,ll,rr);
        else if (ll > mid) return query(rson,ll,rr);
        else return gcd(query(lson,ll,rr),query(rson,ll,rr));
    }
     
    void pushUp(int rt) {
        s[rt] = s[2 * rt] + s[2 * rt + 1];
    }
     
    void pushDown(int rt, int l, int r) {
        if(k[rt] == 0) return;
        int mid = (l + r) / 2;
        s[2 * rt] += (k[rt] * (mid - l + 1));
        s[2 * rt + 1] += (k[rt] * (r - mid));
        k[2 * rt] += k[rt];
        k[2 * rt + 1] += k[rt];
        k[rt] = 0;
    }
     
    void update(int L, int R, long long val, int l, int r, int rt) {
        if(L <= l && r <= R) {
            s[rt] += (val * (r - l + 1));
            k[rt] += val;
            return;
        }
        int mid = (l + r) / 2;
        pushDown(rt, l, r);
        if(L <= mid) update(L, R, val, l, mid, 2 * rt);
        if(R > mid) update(L, R, val, mid + 1, r, 2 * rt + 1);
        pushUp(rt);
    }
     
    long long get(int L, int R, int l, int r, int rt) {
        if(L <= l && r <= R) return s[rt];
        pushDown(rt, l, r);
        int mid = (l + r) / 2;
        long long left = 0, right = 0;
        if(L <= mid) left = get(L, R, l, mid, 2 * rt);
        if(R > mid) right = get(L, R, mid + 1, r, 2 * rt + 1);
        pushUp(rt);
        return left + right;
    }
     
    struct point{
        int l,r,g, id;
    }c[N];
     
    struct point2 {
        int l1, l2, r, g;
    }h[N];
    int szh;
     
    long long ans[N];
     
    bool cmpc(const point& a, const point& b) {
        if(a.g != b.g) return a.g < b.g;
        return a.r < b.r;
    }
     
    bool cmph(const point2& a, const point2& b) {
        if(a.g != b.g) return a.g < b.g;
        return a.r < b.r;
    }
     
    bool cmpid(const point& a, const point& b ) {
        return a.id < b.id;
    }
     
    int main() {
    #ifdef ZHOUZHENTAO
        freopen("test.in", "r", stdin);
    #endif
     
        scanf("%d", &T);
        int cas = 0;
        while (T--) {
            scanf("%d", &n);
            build(1, 1, n);
            scanf("%d", &m);
            printf("Case #%d:
    ", ++cas);
            for (int i = 0;i< m ;i++) {
                scanf("%d%d", &c[i].l, &c[i].r);
                c[i].g = query(1, 1, n, c[i].l, c[i].r);
                c[i].id = i;
            }
     
            szh = 0;
            stack<pii> a, b;
            rep(i, 1, n) {
                a.push(mp(d[i], 1));
                while (!a.empty()) b.push(mp(gcd(a.top().ff, d[i]), a.top().ss)), a.pop();
                while (!b.empty()) {
                    pii q = b.top();    b.pop();
                    if (!a.empty() && a.top().ff == q.ff) q.ss += a.top().ss, a.pop();
                    a.push(q);
                }
     
                int L = i;
                while (!a.empty()) {
                    pii q = a.top(); a.pop();
                    int LL = L - q.second + 1;
                    h[szh].l1 = LL;
                    h[szh].l2 = L;
                    h[szh].r = i;
                    h[szh].g = q.first;
                    szh ++;
                    L = LL - 1;
                    b.push(q);
                }
                while (!b.empty()) {
                    a.push(b.top()); b.pop();
                }
            }
     
            sort(c, c + m, cmpc);
            sort(h, h + szh, cmph);
            /* 
                    for(int i = 0; i < szh; i ++) {
                    cout << h[i].l1 << " " << h[i].l2 << " " << h[i].r << " " << h[i].g << endl;
                    }
     
                    for(int i = 0; i < m; i ++) {
                    cout << c[i].l << " " << c[i].r << " " << c[i].g << endl;
                    }
             */
            for(int i = 0; i < m; i ++) {
                ans[i] = 0;
            }
            for(int i = 0, j = 0; i < szh; i = j + 1, j = i) {
                while(j < szh - 1 && h[j].g == h[j + 1].g) j ++;
                // [i, j]
     
                int L = 0, R = m - 1, pos1 = -1, pos2 = -1;
                while(L <= R) {
                    int mid = (L + R) / 2;
                    if(c[mid].g < h[i].g) L = mid + 1;
                    else if(c[mid].g > h[i].g) R = mid - 1;
                    else pos1 = mid, R = mid - 1;
                }
     
                if(pos1 == -1) continue;
     
                L = 0, R = m - 1;
                while(L <= R) {
                    int mid = (L + R) / 2;
                    if(c[mid].g < h[i].g) L = mid + 1;
                    else if(c[mid].g > h[i].g) R = mid - 1;
                    else pos2 = mid, L = mid + 1;
                }
     
                //[pos1, pos2]
                /*
                     printf("[%d, %d]  [%d, %d]
    ", i, j, pos1, pos2);
                 */
                int y = i;
                for(int k = pos1; k <= pos2; k ++) {
                    while(y <= j && h[y].r <= c[k].r) {
                        update(h[y].l1, h[y].l2, 1LL, 1, n, 1);
                        y ++;
                    }
                    ans[c[k].id] = get(c[k].l, c[k].r, 1, n, 1);
                }
     
                for(int k = i; k < y; k ++) {
                    update(h[k].l1, h[k].l2, -1LL, 1, n, 1);
                }
     
            }
     
            sort(c, c + m, cmpid);
            for(int i = 0; i < m; i ++) {
                printf("%d ", c[i].g);
                printf("%lld
    ", ans[i]);
            }
     
        }
        return 0;
    }
    

    J - 杯子

    这题和这题完全一样。

    #include <bits/stdc++.h>
    using namespace std;
     
    typedef long long LL;
    LL p = 1e9 + 7;
     
    const int maxn = 3e6 + 10;
    LL f[maxn];
     
    //******************************
    //返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
    long long extend_gcd(long long a,long long b,long long &x,long long &y)
    {
      if(a==0&&b==0) return -1;//无最大公约数
      if(b==0){x=1;y=0;return a;}
      long long d=extend_gcd(b,a%b,y,x);
      y-=a/b*x;
      return d;
    }
    //*********求逆元素*******************
    //ax = 1(mod n)
    long long mod_reverse(long long a,long long n)
    {
      long long x,y;
      long long d=extend_gcd(a,n,x,y);
      if(d==1) return (x%n+n)%n;
      else return -1;
    }
     
    LL C(LL n, LL m) {
      long long A = f[n];
      long long B = f[n - m] * f[m] % p;
      long long C = mod_reverse(B, p);
      return A * C % p;
    }
     
    LL work(LL n, LL m) {
      if(n == m) return 1;
      return (C(n * 2 - m - 1, n - m)
              - C(n * 2 - m - 1, n - m - 1)
              + p) % p;
    }
     
    int main() {
      f[0] = 1;
      for(long long i = 1; i < maxn; i ++) {
        f[i] = (f[i - 1] * i) % p;
      }
      int T;
      scanf("%d", &T);
      while(T --) {
        LL n, m, k;
        scanf("%lld%lld%lld", &n, &m, &k);
        if(m > n || m < k) {
          printf("0
    ");
          continue;
        }
        LL A = work(m, k);
        LL B = work(n + k + 1 - m, k + 1);
        LL ans = A * B % p;
        printf("%lld
    ", ans);
      }
      return 0;
    }
    /*
      
     A:
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   1
     2  |   1    1
     3  |   2    2    1
     4  |   5    5    3    1
     5  |  14   14    9    4    1
     6  |  42   42   28   14    5    1
     7  | 132  132   90   48   20    6    1
      
     B:
     n = 1
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   1
     2  |
     3  |
     4  |
     5  |
     6  |
     7  |
      
     n = 2
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   2
     2  |   1    1
     3  |
     4  |
     5  |
     6  |
     7  |
      
     n = 3
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   5
     2  |   2    3
     3  |   1    1    1
     4  |
     5  |
     6  |
     7  |
      
     n = 4
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   14
     2  |   5    9
     3  |   2    3    4
     4  |   1    1    1   1
     5  |
     6  |
     7  |
      
     n = 5
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   42
     2  |   14  28
     3  |   5    9   14
     4  |   2    3    4    5
     5  |   1    1    1    1    1
     6  |
     7  |
      
     */
    

    K - zzq的离散数学教室2

    这题看上去好像和 2017 ICPC 南宁 M 题一样,都是求最长反链长度。最长反链长度 = 最小链覆盖数,原题在 BZOJ 1143。两种做法:第一种做法传递闭包搞,第二种做法网络流上对流量做一些改造。第二种能适应这题的数据规模。

    L - 仓鼠养殖计划

    队友写的,我题意都不知道。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 1e5 + 10;
    int T,a,b,n, c[N];
     
    bool check() {
        for (int i = 1;i<=n;i++) {
            while (c[i]) {
                if (a+b==0) break;
                if (a==0) {
                    c[i] = max(0,c[i]-2);
                    b--;
                }
                else if (b==0) {
                    c[i]--; a--;
                }
                else if (c[i]>1) {
                    c[i]-=2; b--;
                }
                else {
                    c[i]--; a--;
                }
            }
            if (c[i]) return false;
        }
        return true;
    }
     
    int main(){
        for (scanf("%d",&T);T--;) {
            scanf("%d%d%d",&a,&b,&n);
            for (int i = 1;i<=n;i++) {
                scanf("%d",&c[i]);
            }
            puts(check()?"Yes":"No");
        }
        return 0;
    }
    
  • 相关阅读:
    Week4_1Neural Networks Representation
    吴恩达逻辑回归题目详解
    丢弃正则化
    python随笔 join 字典,列表的清空 set集合 以及深浅拷贝(重点..难点)
    python全栈开发 随笔 'is' 和 == 的比较知识与区别 编码和解码的内容及转换
    python全栈 字典数据类型相关知识及操作
    Python全栈开发 列表, 元组 数据类型知识运用及操作 range知识
    python全栈 字符串,整数,bool 数据类型运用
    python全栈 流程控制;while 循环 格式化输出 运算符 及编码
    python全栈开发 什么是python python命名及循环
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8835707.html
Copyright © 2011-2022 走看看