Educational Codeforces Round 68 (Rated for Div. 2) D. 1-2-K Game (博弈, sg函数,规律)

匿名 (未验证) 提交于 2019-12-02 23:48:02

D. 1-2-K Game
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output

Who wins if both participants play optimally?

Alice and Bob would like to play several games, so you should determine the winner in each game.

Input

Output
For each game, print Alice if Alice wins this game and Bob otherwise.

Example
inputCopy
4
0 3
3 3
3 4
4 4
outputCopy
Bob
Alice
Bob
Alice

题意:
当前在n位置,每一次可以向左走1,2,或者k步,最左的位置是0,不能走到0之后, 二人博弈问题,谁没发走谁输,问先手必赢还是后手必赢。
思路:

首先确定的是 0位置是必数位置,因为 1 2 和k这三个位置可以一步就走到0位置,所以这3个位置是必赢位置,以此规律,我们可以递推出sg函数。

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;} inline void getInt(int* p); const int maxn=1000010; const int inf=0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ int sg[maxn]; int main() {     //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);     //freopen("D:\\common_text\code_stream\\out.txt","w",stdout);          int n,k;     n=100;     cin>>k;     sg[0]=0;     sg[1]=1;     sg[2]=1;     repd(i,3,n)     {         if((i-k)>=0)         {             if(sg[i-1]==0||sg[i-2]==0||sg[i-k]==0)             {                 sg[i]=1;             }         }else         {             if(sg[i-2]==0||sg[i-1]==0)             {                 sg[i]=1;             }         }     }     repd(i,0,n)     {         cout<<i<<" "<<sg[i]<<endl;      }                    return 0; }  inline void getInt(int* p) {     char ch;     do {         ch = getchar();     } while (ch == ' ' || ch == '\n');     if (ch == '-') {         *p = -(getchar() - '0');         while ((ch = getchar()) >= '0' && ch <= '9') {             *p = *p * 10 - ch + '0';         }     }     else {         *p = ch - '0';         while ((ch = getchar()) >= '0' && ch <= '9') {             *p = *p * 10 + ch - '0';         }     } }  

通过sg函数打表分析可以得出, 有以下规律 如果k是3的倍数,那么sg函数是k+1长度的循环节,对循环节取模后,判断n是否是k,如果是k,那么k位置必赢,否则判断是否是3的倍数。 如果k不是3的倍数,那么判断n是否是3的倍数即可。  比赛时看错表,推出个错规律,wa了3次,深夜写这个博客算给自己一个记性吧。

细节见代码:

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 1000010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/   int main() {     //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);     //freopen("D:\\common_text\code_stream\\out.txt","w",stdout);       int t;     ll n, k;     gbtb;     cin >> t;     while (t--)     {         cin >> n >> k;         if (k % 3 == 0)         {             n %= (k + 1);             if (n == k)             {                 cout << "Alice" << endl;             } else             {                 if (n % 3 == 0)                     cout << "Bob" << endl;                 else                     cout << "Alice" << endl;             }             // return 0;             continue;         }           if ((n % 3) == 0 )         {             cout << "Bob" << endl;         } else         {             cout << "Alice" << endl;         }     }           return 0; }   inline void getInt(int* p) {     char ch;     do {         ch = getchar();     } while (ch == ' ' || ch == '\n');     if (ch == '-') {         *p = -(getchar() - '0');         while ((ch = getchar()) >= '0' && ch <= '9') {             *p = *p * 10 - ch + '0';         }     }     else {         *p = ch - '0';         while ((ch = getchar()) >= '0' && ch <= '9') {             *p = *p * 10 + ch - '0';         }     } }      
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!