CodeForces - 603C Lieges of Legendre(博弈+找规律)
題目鏈接:點(diǎn)擊查看
題目大意:首先給出n堆石子和一個(gè)k值,兩人輪流按照規(guī)則操作,不能操作的一方即為失敗,每一次都有兩種操作:
兩人都會(huì)按照最優(yōu)解操作,問誰能贏得游戲
題目分析:我們可以將n堆石子都看成一個(gè)獨(dú)立的游戲,那么這個(gè)題目就轉(zhuǎn)換成了求每一堆石子的sg函數(shù)然后異或判斷結(jié)果,但這里遇到了兩個(gè)問題,首先這個(gè)題目不是常規(guī)的sg打表,其次每一堆石子的數(shù)目達(dá)到了1e9,打表是不太現(xiàn)實(shí)的
我們可以先打個(gè)表看一下前幾項(xiàng)規(guī)律,看了網(wǎng)上大部分的博客都沒有教怎么打表找規(guī)律,昨天我問了問我隊(duì)友,確實(shí)挺簡單的,但我不會(huì)。。現(xiàn)在可算是會(huì)了
先簡單分析一下,不難看出,若這個(gè)sg函數(shù)主要取決于k的奇偶,若k為奇數(shù),那么除了一堆之外,其他的都能互相抵消掉,若k為偶數(shù),那么所有新生成的堆數(shù)都能互相抵消,有了這個(gè)結(jié)論,我們就能得出sg函數(shù)的大體框架了:
sg函數(shù):
const int N=100;//打表打到多少int sg[N];bool mex[10];void get_sg() {sg[0]=0;for(int i=1;i<N;i++){memset(mex,false,sizeof(mex));if(i&1)mex[sg[i-1]]=true;else{if(k&1){mex[sg[i-1]]=true;mex[sg[i/2]]=true;}else{mex[sg[i-1]]=true;mex[sg[0]]=true;}}for(int j=0;j<10;j++)if(!mex[j]){sg[i]=j;break;}} }然后我們就可以找規(guī)律了,我們可以輕易的看出,當(dāng)x為較大的奇數(shù)時(shí)(大于3的奇數(shù)),sg函數(shù)值都是0,即為必?cái)B(tài),那么在處理偶數(shù)時(shí),只需要關(guān)注其除以2的sg函數(shù)值即可,因?yàn)槿羝淠苤苯拥竭_(dá)奇數(shù)態(tài)時(shí),那么其sg的值必為1,就可以直接返回了
當(dāng)x為偶數(shù)時(shí),就要根據(jù)k的奇偶來判斷了,一開始我以為sg函數(shù)值和x中有2的冪次有關(guān)系,后來發(fā)現(xiàn)不太對,自己觀察(去網(wǎng)上搜題解)后得出,因?yàn)閗為偶數(shù)時(shí)對結(jié)果沒有影響,所以x的sg值都為1,當(dāng)k為奇數(shù)時(shí),就要判斷x/2的sg值了,一直往前遞歸,就能根據(jù)前面的值推出當(dāng)前的值了,大概的一個(gè)邏輯就是:
這個(gè)邏輯結(jié)合上面提到的sg函數(shù)的邏輯就很好理解了,如果實(shí)在不行,或者找規(guī)律技術(shù)屬實(shí)強(qiáng)大,那么可以直接找規(guī)律看出來
實(shí)現(xiàn)代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;int k; /* 當(dāng)k為偶數(shù): 0:0 1:1 2:2 從3開始: 奇數(shù):0 偶數(shù):1當(dāng)k為奇數(shù): 0:0 1:1 2:0 3:1 4:2 奇數(shù):0 偶數(shù):與x/2的sg有關(guān):x/2=2或x/2=0:1x/2=1:2 */ int get_sg(int x) {if(k&1){if(x<5){if(x==0)return 0;else if(x==1)return 1;else if(x==2)return 0;else if(x==3)return 1;else if(x==4)return 2;}else{if(x&1)return 0;elsereturn get_sg(x/2)==1?2:1; }}else{if(x<=2)return x;elsereturn (x&1)^1; } }int main() { // freopen("input.txt","r",stdin);int n;scanf("%d%d",&n,&k);int ans=0;while(n--){int num;scanf("%d",&num);ans^=get_sg(num);} if(ans)printf("Kevin\n");elseprintf("Nicky\n");return 0; }?
總結(jié)
以上是生活随笔為你收集整理的CodeForces - 603C Lieges of Legendre(博弈+找规律)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PAT (Basic Level) 10
- 下一篇: CodeForces - 850C Ar