Hackerrank---A stones game

/**
这道题的sg函数为sg(n)=min{m|2**m>n}
当石堆的数目为奇数时,相邻两个石堆异或为0,只余下第一堆,之拿走一个就可以
当石堆的数目为偶数时,剩下最后一个石堆和第一个石堆。那么就有两种情况,要么从最大堆拿走尽可能少的石子。要么从前面一堆拿走尽可能少的石子,使他们的异或和等于最大堆和1的异或值。
最坏情况是N=2**n,此使要拿走的石子数是N-1
**/

int half(int n) {
if(n%2==1){
return 1;
}
int nim,k;
int ans=n-1;
nim=0,k=n;
while(k){nim++;k/=2;}
if(nim%2==0)
{
nim=nim+1;
}else{
nim=nim-1;
}
for(int i=2;i<=nim;i++){
for(int j=0;j<i;j++){
if((nim^i^j)==0){
if(i-j==1){
ans=min(ans,1<<(j-1));
}else{
ans=min(ans,(1<<(i-1))-(1<<j)+1);
}
}
}
}
return ans;
}

int main()
{
ofstream fout(getenv("OUTPUT_PATH"));

string t_temp;
getline(cin, t_temp);

int t = stoi(ltrim(rtrim(t_temp)));

for (int t_itr = 0; t_itr < t; t_itr++) {
string n_temp;
getline(cin, n_temp);

int n = stoi(ltrim(rtrim(n_temp)));

int result = half(n);

fout << result << "\n";
}

fout.close();

return 0;
}

string ltrim(const string &str) {
string s(str);

s.erase(
s.begin(),
find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace)))
);

return s;
}

string rtrim(const string &str) {
string s(str);

s.erase(
find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(),
s.end()
);

return s;
}

posted @ 2021-05-28 16:26  darkwill  阅读(48)  评论(0编辑  收藏  举报