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


D. 1-2-K Game
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Alice and Bob play a game. There is a paper strip which is divided into n + 1 cells numbered from left to right starting from 0. There is a chip placed in the n-th cell (the last one).

Players take turns, Alice is first. Each player during his or her turn has to move the chip 1, 2 or k cells to the left (so, if the chip is currently in the cell i, the player can move it into cell i - 1, i - 2 or i - k). The chip should not leave the borders of the paper strip: it is impossible, for example, to move it k cells to the left if the current cell has number i < k. The player who can't make a move loses the game.

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
The first line contains the single integer T (1 ≤ T ≤ 100) — the number of games. Next T lines contain one game per line. All games are independent.

Each of the next T lines contains two integers n and k (0 ≤ n ≤ 109, 3 ≤ k ≤ 109) — the length of the strip and the constant denoting the third move, respectively.

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';
        }
    }
}
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM