HDU-4664 Triangulation(博弈SG打表+类似凸包性质)

来源:互联网 发布:长春java公司 编辑:程序博客网 时间:2024/06/05 19:34

题意:

给n个平面,每个面包含若干点,每个平面的所有点都在该平面上构成一个凸包。每个人依次选择两个点进行连边(直线段),但他们的连边不能相交,最终不能操作的人输,求胜者。

思路:

根据凸包,我们知道任意两点相连,那么其就将所有的点分成两部分了,这两部分之间的点如果想进行连边,则必然与其有交点。所以就能将sg函数就能写出来了。


然后打表会很艰难的发现,到34的时候,出现了第一次循环节,然后在第68之后,就一直在重复新的循环节了。

代码:

#include <bits/stdc++.h>#define ll long longusing namespace std;const int maxn = 1005;int sg[maxn], mex[maxn];void getSG(){    sg[0] = sg[1] = 0;    sg[2] = 1;    //cout << 0 << " ";    //cout << 0 << " ";    //cout << 1 << " ";    for(int i = 3; i <= 200; ++i)    {        memset(mex, 0, sizeof mex);        for(int j = 2; j-2 <= i-j; ++j)            mex[sg[j-2] ^ sg[i-j]] = 1;        for(int j = 0; ; ++j)        if(!mex[j])        {            sg[i] = j;            break;        }        //cout << sg[i] << " ";        //if(i%34 == 0) cout << endl;    }}int val(int x){    if(x <= 68) return sg[x];    int k = x%34;    return sg[68+k];}int main(){    ios::sync_with_stdio(0);    getSG();    int t, n, x, ans;    cin >> t;    while(t--)    {        cin >> n; ans = 0;        for(int i = 1; i <= n; ++i)        {            cin >> x;            ans ^= val(x);        }        if(ans) cout << "Carol" << endl;        else cout << "Dave" << endl;    }    return 0;}


继续加油~

原创粉丝点击