Written with StackEdit.
有\(n\)堆石子,第\(i\)堆有\(x_i\)个。
\(Alice\)和\(Bob\)轮流取石子(先后手未定),\(Alice\)每次从一堆中取走\(a\)个,\(Bob\)每次从一堆中取走\(b\)个,无法操作者输。
不难发现只会有四种情况:\(Alice\)必胜;\(Bob\)必胜;先手必胜;后手必胜。
你需要选定若干堆石子(共有\(2^n\)种方案),\(Alice\)和\(Bob\)只能在你选出的堆中取,问以上四种情况对应的方案数。对\(10^9+7\)取模。
第一行三个整数\(n,a,b\),第二行\(n\)个整数\(x_1.....x_n\)。
一行四个整数,分别表示\(Alice\)必胜、\(Bob\)必胜、先手必胜和后手必胜的方案数,对\(10^9+7\)取模。
2 2 3
2 3
2 0 1 1
选定空集时后手必胜,选定{\(2\)}时\(Alice\)必胜,选定{\(3\)}时先手必胜,选定{\(2,3\)}时\(Alice\)必胜。
对于\(10\%\)的数据,\(n,x_i\leq 5\)。
对于\(50\%\)的数据,\(n\leq 20\)。
对于另外\(10\%\)的数据,\(a=b\)。
对于又另外\(20\%\)的数据,\(a=1\)。
对于\(100\%\)的数据,\(1\leq n\leq 100000,1\leq a,b,x_i\leq 10^9\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>='0'&&jp<='9')
        {
            out=out*10+jp-'0';
            jp=getchar();
        }
    return out*fh;
}
const int P=1e9+7;
inline int add(int a,int b)
{
    return (a+b) % P;
}
inline int mul(int a,int b)
{
    return 1LL * a * b % P;
}
inline int sub(int a,int b)
{
    return (add(a,-b)+P)%P;
}
int fpow(int a,int b)
{
    int res=1;
    while(b)
        {
            if(b&1)
                res=mul(res,a);
            a=mul(a,a);
            b>>=1;
        }
    return res;
}
int flag=0;
int calcodd(int x)
{
    if(!x)
        return 0;
    return fpow(2,x-1);
}
int calceven(int x)
{
    if(!x)
        return 1;
    return fpow(2,x-1);
}
int x[4],ans[4];
int main()
{
    int n,a,b;
    freopen("stone.in","r",stdin);
    freopen("stone.out","w",stdout);
    n=read(),a=read(),b=read();
    if(a>b)
        swap(a,b),flag=1;
    for(int i=1; i<=n; ++i)
        {
            int r=read();
            r%=(a+b);
            if(r<a)
                ++x[0];
            else if(r>=a && r<b)
                ++x[1];
            else if(r>=b && r<2*a)//这个区间可能为空集.加上else.
                ++x[2];
            else if(r>=2*a)
                ++x[3];
        }
    ans[2]=mul(x[3],calceven(x[2]));
    ans[2]=add(ans[2],calcodd(x[2]));
    ans[2]=mul(ans[2],fpow(2,x[0]));
    ans[3]=calceven(x[2]);
    ans[3]=mul(ans[3],fpow(2,x[0]));
    ans[0]=sub(fpow(2,n),add(ans[2],ans[3]));
    if(flag)
        swap(ans[0],ans[1]);
    for(int i=0; i<4; ++i)
        printf("%d ",ans[i]);
    return 0;
}
占坑.
占坑.
原文:https://www.cnblogs.com/jklover/p/10168260.html