LETTers比赛第十二场解题报告
LETTers比赛第十二场解题报告
提交人:周杰
第一题:
典型的misere nim问题。
可以通过拓展的nim游戏的证明来求解。单一nim游戏的证明是通过证明N和P态,然后证明必然的路径和终止状态的归属来证明的。这道题也是一样。
具体证明可以参考09年国家集训队贾志豪的论文,或者参考我放在群共享里的game theory教材,或者下面这篇证明:
http://blog.csdn.net/tdreamge/article/details/7227295。
放上我的核心代码:
int t;
int num1, num2;
int n;
int data;
int ans;
int main (int argc, const char* argv[]) {
scanf("%d", &t);
For(i, 0, t) {
scanf("%d", &n);
ans = 0;
num1 = 0; num2 = 0;
For(j, 0, n) {
scanf("%d", &data);
if (data >= 2) num2++;
if (data == 1) num1++;
ans = ans ^ data;
}
if (ans == 0) {
if (num2 >= 2) printf("Brother\n");
if (num2 == 0) printf("John\n");
} else {
if (num2 == 0) printf("Brother\n");
else if (num2 >= 1) printf("John\n");
}
}
return 0;
}
第二题:这道题是很裸的dijkstra。。表示这道题是送AC的。
代码不放了。
第三题:Josephus问题。这道题因为只要求最后一个人的编号,所以可以递归求解。
简单给出递归公式:f(n)= (f(n - 1)+ m) % n;
最后输出f(n) + 1。
代码:
int ans[1000005];
int n, d;
int main (int argc, const char* argv[]) {
while (scanf("%d %d", &n, &d) && (n || d)) {
memset(ans, 0, sizeof(ans));
ans[1] = 0;
For(i, 2, n + 1) ans[i] = (ans[i - 1] + d) % i;
printf("%d %d %d\n", n, d, ans[n] + 1);
}
return 0;
}
当然也可以不开ans数组,速度更快。
第四题:暴力枚举。
一个基本事实:一个数的因子是logn级别。
接着可以发现复杂度不会超过nlogn*logn。
参考代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<ctime>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
const int maxn=100000+1;int n;
vector<int> A[maxn];
typedef vector<int>::iterator it;
typedef vector<int>::reverse_iterator rit;
typedef long long ll;
void Cal(int x)
{
static int tmp[10000];
int cnt=0;
for(int i=1;i*i<=x;i++)if(x%i==0)
tmp[cnt++]=i,tmp[cnt++]=x/i;
sort(tmp,tmp+cnt);A[x].push_back(tmp[0]);
for(int j=1;j<cnt;j++)
if(tmp[j]!=tmp[j-1])
A[x].push_back(tmp[j]);
}
int Ans[maxn*50];
int main()
{
cin>>n;
for(int i=1;i<n;i++) Cal(i);
int ans=0;
for(int a=1;a<n;a++)
{
int*end=Ans;
for(int l=a;l<n;l+=a)
{
int r=n-l;
for(rit i=A[r].rbegin();i!=A[r].rend();i++)
if(*i>a) *(end++)=*i;
else break;
}
if(Ans==end) continue;
sort(Ans,end);
ans++;
for(int*i=Ans+1;i!=end;i++)
if(*i!=*(i-1)) ans++;
}
cout<<ans<<endl;
}