zoukankan      html  css  js  c++  java
  • 20201005国庆day3

    博弈论:

    1.公平组合游戏:
      若一个游戏满足:
            a.两名玩家交替行动。
            b.在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关。
            c.不能行动的玩家判负。
      则为一个公平组合游戏。
    
    2.状态图:
      在公平组合游戏中可以用有向无环图表示状态,p态和n态。p状态表示该状态对于前一个玩家必胜,n状态表示该状态对于后一个玩家必胜。
      大部分游戏中,终止状态是p态。任意一个p态,它要么是一个终止状态,要么它所有可以转移到的状态都是n态。而对于任意一个n态,至少有一个后继状态是p态。
    
    3.Nim游戏

    n堆石子,第i堆有(a_i)个,两玩家轮流挑选一堆石子,取走若干个,最后不能取的是输家。
    对于当前状态 (a=(a_1,a_2...a_n)),如果 (a_1hat{}a_2hat{}...hat{}a_n=0),则为p态,否则为n态。
    结论:Nim博弈先手必胜,当且仅当 (a_1hat{}a_2hat{}...hat{}a_n eq0)

    T1(nim游戏和经典取石子游戏的结合)

    对于x的答案,我们将每个数都mod(x+1),并求出异或和。假如异或和为0,则假如Alice取某堆石子的数量超过了余数,Bob可以取同一堆的石子使得余数变回去。如果Alice取的不超过某堆石子的余数,那么游戏变为经典的nim游戏,所以异或和为0先手必败,否则必胜。
    所以问题变为求所有可能的x对应的 (a_imod(x+1))的异或和。

    50pts。。。

    T2

    30pts思路:维护三个堆,分别为x能吃的鱼,x不能吃的鱼,已经吃了的鱼。来回倒腾就行。
    24pts代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    signed main(){
    	priority_queue<int>q;
    	priority_queue<int,vector<int>,greater<int> >l;
    	priority_queue<int>eat;
    	int n,a;scanf("%lld",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a);q.push(a);
    	}
    	scanf("%lld",&a);
    	int chk;
    	while(a--){
    		scanf("%lld",&chk);
    		int x,y;
    		if(chk==2){
    			scanf("%lld",&x);
    			q.push(x);
    		}
    		else if(chk==3){
    			scanf("%lld",&x);
    			while(q.top()>x){
    				l.push(q.top());
    				q.pop();
    			}
    			q.pop();
    			while(!l.empty()){
    				q.push(l.top());
    				l.pop();
    			}
    		}
    		else{
    			int cnt=0;
    			scanf("%lld%lld",&x,&y);
    			while(q.top()>=x){
    				l.push(q.top());
    				q.pop();
    			}
    			while(!q.empty()){
    				if(x>=y)break;
    				x+=q.top();
    				cnt++;
    				eat.push(q.top());
    				q.pop();
    				while(l.top()<x&&!l.empty()){
    					q.push(l.top());
    					l.pop();
    				}
    			}
    			if(x>=y)printf("%lld
    ",cnt);
    			else printf("-1
    ");
    			while(!l.empty()){
    				q.push(l.top());l.pop();
    			}
    			while(!eat.empty()){
    				q.push(eat.top());eat.pop();
    			}
    		}
    	}
    	return 0;
    }
    

    正解:线段树二分。

    T3

    40pts:(n^2)暴力显然
    100pts:计算范围内倍数数量即可。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    using namespace std;
    const int mod=1e9+7;
    int gcd(int a,int b){
        if (a%b==0) return b;
        gcd(b,a%b);
    }
    ll a,b,c,d;
    int main(){
        scanf ("%lld%lld%lld%lld",&a,&b,&c,&d);
        ll ans=0;
        for (int i = 1;i <= 999;i++){
            for (int j = 1;j <= 999;j++){
                if (gcd(i,j)==1){
                    ll l=max((a-1)/i+1,(c-1)/j+1),r=min(b/i,d/j);
                    ans=(ans+max((ll)(0),r-l+1)*(i+j))%mod;
                }
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    后缀数组模板~~~
    CF 196 Div2 D&&HDU 4679 && HDU 2196
    .......
    ~~~~~
    主站点~~~~
    C++抽象,封装,继承,多态
    查缺补漏知识点(二)
    Qt的简介
    C语言指针及C++引用
    C++单例模式
  • 原文地址:https://www.cnblogs.com/zdxx/p/13770121.html
Copyright © 2011-2022 走看看