zoukankan      html  css  js  c++  java
  • 20201201模拟

    T1

    problem

    (n)个石子,两个人选,每个人可以选(a)个或(b)个,问是否存在先手必胜的策略

    solution

    • (n mod (a+b) < min(a,b))时,当我先手选(a),后手可以选(b),先手选(b),后手可以选(a),可以保证最后一次后手选完后剩下的石子(<min(a,b)),后手必胜

    • (n mod (a+b) geq max(a,b))时,先手选(max(a,b)),那么现在的石子个数(n' mod (a+b) < min(a,b)),后手变成了我第一种情况的先手,先手必胜

    • 在上述两种情况之间时设(x = n mod (a+b)),可知(min(a,b)leq x < max(a,b)),说明最后我无法选(max(a,b)),此时两个人轮流 选(min(a,b)),

      (x/min(a,b))为奇数时,先手必胜

      (x/min(a,b))为偶数时,后手必胜

    code

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <map>
    #define int long long
    using namespace std;
    int read(){
    	int x = 1,a = 0;char ch = getchar();
    	while (ch < '0'||ch > '9'){if (ch == '-') x = -1;ch = getchar();}
    	while (ch >= '0'&&ch <= '9'){a = a*10+ch-'0';ch = getchar();}
    	return x*a;
    }
    int t,n,a,b;
    signed main(){
    	freopen("nim.in","r",stdin);
    	freopen("nim.out","w",stdout);
    	t = read();
    	while (t--){
    		n = read(),a = read(),b = read();
    		int x = n%(a+b);
    		if (a > b) swap(a,b);
    		if (x < a) {printf("0
    ");continue;}
    		if (x >= b) {printf("1
    ");continue;}
    		if ((x/a)%2 == 0) printf("0
    ");
    		else printf("1
    ");
    	}
    	return 0;
    }
    

    T2

    problem

    每次往车中放入可放石子中最大的一个,直到无法装下任何一个为止,至多运(k)次,求最小装载量

    solution

    很容易想到二分,不过正确性未知,而且我写的混乱的check函数就离谱,就挂了……

    code

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <map>
    #define int long long
    using namespace std;
    int read(){
    	int x = 1,a = 0;char ch = getchar();
    	while (ch < '0'||ch > '9'){if (ch == '-') x = -1;ch = getchar();}
    	while (ch >= '0'&&ch <= '9'){a = a*10+ch-'0';ch = getchar();}
    	return x*a;
    }
    const int maxn = 2005;
    int n,k;
    int a[maxn];
    bool vis[maxn];
    bool check(int w){
    	int j;memset(vis,0,sizeof(vis));
    	for (int i = 1;i <= k;i++){
    		int res = w;
    		for (j = n;j >= 1;j--){
    			if (vis[j]) continue;
    			if (res-a[j] >= 0) res-=a[j],vis[j] = 1;
    			else break;
    		}
    	}
    	if (j == 0) return true;
    	else return false;
    }
    signed main(){
    	freopen("pack.in","r",stdin);
    	freopen("pack.out","w",stdout);
    	n = read(),k = read();
    	int l,r = 0;
    	for (int i = 1;i <= n;i++) a[i] = read(),r += a[i];
    	sort(a+1,a+n+1);l = a[n];
    	while (l < r){
    		int mid = (l+r)>>1;
    		if (check(mid)) r = mid;
    		else l = mid+1;
    	}
    	printf("%lld
    ",r);
    	return 0;
    }
    

    T3

    problem

    (n)堆石子,从现有的石堆中各取一个形成新的石堆,问(k)次操作后石堆的情况

    solution

    每次只有最小的石堆会消失,优先队列维护一下就好了,同时新形成的石堆要加上他形成的那一天的天数,这样才能统一起跑线,使得石子减少的量等于总天数

    code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    using namespace std;
    int read(){
    	int x = 1,a = 0;char ch = getchar();
    	while (ch < '0'||ch > '9'){if (ch == '-') x = -1;ch = getchar();}
    	while (ch >= '0'&&ch <= '9'){a = a*10+ch-'0';ch = getchar();}
    	return x*a;
    }
    const int maxn = 1e5+10;
    priority_queue<int> q;
    int ans[maxn];
    int n,k;
    int main(){
    	freopen("pile.in","r",stdin);
    	freopen("pile.out","w",stdout);
    	n = read(),k = read();
    	for (int i = 1;i <= n;i++){
    		int x = read();q.push(-x);
    	}
    	for (int i = 1;i <= k;i++){
    		int x = q.size();q.push(-(x+i));
    		while (q.top()+i >= 0) q.pop();
    	}
    	int i;
    	for (i = 1;!q.empty();i++){
    		ans[i] = -q.top();q.pop();
    	}i--;
    	printf("%d
    ",i);
    	while (i) printf("%d ",ans[i]-k),i--;
    	return 0;
    }
    
  • 相关阅读:
    YAML 语法小结
    小程序之脚本语言
    小程序WXML 使用小结
    微信小程序 js逻辑
    小程序开发1
    联想Y7000安装Ubuntu16.04/Win10双系统,wifi问题,显卡驱动和CUDA10安装
    VS2015中配置Eigen
    联想Y700安装显卡驱动和CUDA8.0
    php微信生成微信公众号二维码扫描进入公众号带参数
    Y7000 (1)安装ubuntu1604遇到的问题
  • 原文地址:https://www.cnblogs.com/little-uu/p/14069489.html
Copyright © 2011-2022 走看看