题意:链接
方法:sg函数
解析:
tyvj的题大部分都没题解啊- - 不过这样貌似会更好?感觉做这的题都需要自己动脑啊- - 虽然嘴上说着好烦然而心里觉得好评?
回归正题
设sg[x]表示数x的sg值,这好像是废话
然后对于读入的a[i],将所有的a[i]的sg值异或起来如果不是零则先手赢反之后手
维护的时候有个坑。
每次求约数的时候,数组要在sg里开,因为如果递归下去的话,全局变量的话会被更改,会被坑死。
然后就是怎么维护了
对于x,先求约数
之后枚举哪个数不取,将其他的异或(或者先都异或起来的和去跟每个异或会更快)
然后就AC了
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 110
using namespace std;
int n,cnt;
int num[N];
int sg[1010];
int b[1100];
void get(int x)
{
cnt=1,b[cnt]=1;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
if(i*i==x)b[++cnt]=i;
else b[++cnt]=i,b[++cnt]=x/i;
}
}
}
int ssgg(int x)
{
if(sg[x]!=-1)return sg[x];
int v[1010];memset(v,0,sizeof(v));
get(x);
int tot=cnt,cal[110];
for(int i=1;i<=cnt;i++)cal[i]=b[i];
for(int i=1;i<=tot;i++)
{
int ans=0;
for(int j=1;j<=tot;j++)
{
if(i==j)continue;
ans^=ssgg(cal[j]);
}
v[ans]=1;
}
for(int i=0;;i++)if(!v[i])return sg[x]=i;
}
int main()
{
while(~scanf("%d",&n))
{
memset(sg,-1,sizeof(sg));sg[1]=0;
for(int i=1;i<=n;i++)scanf("%d",&num[i]);
int ans=0;
for(int i=1;i<=n;i++)
{
ans^=ssgg(num[i]);
}
if(ans)printf("freda\n");
else printf("rainbow\n");
}
}