Mod M game (博弈论)

题意

黑板上有2n个数,A和B轮流取数,和记为S和T,若 ( S − T ) % M = 0 (S-T)\%M=0 (ST)%M=0,B赢,否则A赢,A先手。

constrains:
1 ≤ n ≤ 2 e 5 1\leq n\leq 2e5 1n2e5
2 ≤ M ≤ 1 e 9 2\leq M \leq 1e9 2M1e9
0 ≤ a i ≤ M − 1 0\leq a_i \leq M-1 0aiM1

思路

一个后手赢的明显操作是B复制A的操作。形式上,令数字为节点,相同的数字连红边。取决于图是否有完美匹配。然后WA了,有一个很不明显的策略。需要有良好的分类讨论习惯才比较容易不靠瞎蒙看出来。
考虑 N = 2 N=2 N=2,四个数为 b , c , d , e b,c,d,e b,c,d,e,且不存在相等。探究Bob有无赢的可能,有:
( b + c ) % m = k 1 , ( d + e ) % m = k 1 (b+c)\%m=k_1,(d+e)\%m=k_1 (b+c)%m=k1,(d+e)%m=k1
( b + d ) % m = k 2 , ( c + e ) % m = k 2 (b+d)\%m=k_2,(c+e)\%m=k_2 (b+d)%m=k2,(c+e)%m=k2
方程相加相减可得
2 b ≡ 2 e ( m o d M ) 2b\equiv2e \pmod M 2b2e(modM) 2 c ≡ 2 d ( m o d M ) 2c\equiv2d \pmod M 2c2d(modM)
方程有唯一解的条件是modM的循环群中有2的逆元,即M为奇数时,必有b=e,c=d,M为偶数时,有两类解:
b ≡ e + M 2 ∨ b ≡ e ( m o d M ) b\equiv e+\frac{M}{2}\lor b\equiv e \pmod M be+2Mbe(modM)
逆元存在性:
当A与P互质时,A在P意义下的逆元才存在。
特别当P为质数时A必须要不是P的倍数,A在P意义下的逆元才存在, A p h i ( P ) − 1 A^{phi(P)-1} Aphi(P)1
结论可以形式化为:
给定一个图,相同的数字连红边,两数之差模M得M/2的点连蓝边,若存在完美匹配,且只使用偶数条蓝边,Bob可以赢。

代码

#include<bits/stdc++.h>
using namespace std;
#define pow2(X) (1ll<<(X))
#define SIZE(A) ((int)A.size())
#define LENGTH(A) ((int)A.length())
#define ALL(A) A.begin(),A.end()
#define F(i,a,b) for(ll i=a;i<=(b);++i)
#define dF(i,a,b) for(ll i=a;i>=(b);--i)
#define GETPOS(c,x) (lower_bound(ALL(c),x)-c.begin())
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define pb push_back
#define pr pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define eps 1e-6
#define PI acos(-1.0)
#define lb lower_bound
#define ub upper_bound
#define bs binary_search
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
#define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
#define es(x,e) (int e=fst[x];e;e=nxt[e])
#define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
#define SZ 666666
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> ipair;
typedef vector<int> VI;
typedef vector<long long> VLL;
typedef vector<vector<long long > > VVLL;
typedef vector<vector<int> > VVI;
typedef vector<double> VD;
typedef vector<string> VS;
//const int mods = 998244353;
const int mods = 1e9+7;
const int maxn = 4e5+10;
const int N = 5e5+10;
const int E = 1e4+10;
const int lim = 1e9;
ll qpow(ll a,ll b) {ll res=1;a%=mods; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mods;a=a*a%mods;}return res;}
ll lcm(ll a, ll b) {return a / __gcd(a, b) * b;}
int read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}

int n,q,m;
int a[maxn];

int main(){
	// freopen("C:\\Users\\Gao\\Desktop\\validation_input\\watering_well_chapter_2_input.txt","r",stdin);
	// freopen("C:\\Users\\Gao\\Desktop\\validation_input\\output.txt","w",stdout);
    
	ios_base::sync_with_stdio(0);
    int T;
    //cin>>T; 
	T = 1;
	F(turn,1,T){
		cin>>n>>m;
		map<int,int> cnt;
		F(i,1,2*n){
			cin>>a[i];
			a[i]%=m;
		}
		bool flg = 0;
		if(m&1){
			F(i,1,2*n) cnt[a[i]]^=1;
			for(auto [u,v]:cnt){
				if(v!=0){
					flg = 1;
					break;
				}
			}
		}
		else{
			F(i,1,2*n) cnt[a[i]]^=1;
			int res = 0;
			for(auto [u,v]:cnt){
				if(v!=0){
					if(cnt[(u+m/2)%m]==1){
						cnt[(u+m/2)%m]--;
						res++;
					}
					else{
						flg = 1;
						break;
					}
				}
				cnt[u] = 0;
			}
			if(res&1) flg = 1;
		}
		if(flg){
			cout<<"Alice\n";
		}
		else cout<<"Bob\n";
	}
}
 
/*
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值