版权声明:博主是个蒟蒻,希望大家支持,如果要转发就转发吧,把我链接挂上即可。 https://blog.csdn.net/LightningUZ/article/details/88917775
题意简述
设 为n的所有因数异或起来的结果,求 的值。
数据
输入:4
输出:7
解释
f(1)=1
f(2)=1^2
f(3)=1^3
f(4)=1^2^4
4个异或起来是1^3^2^7=7
思路
多亏样例解释写成这样工整的表格形式才让我早一点看出来!我们换个角度想想,我们枚举1~n里每个数的因数,设为d,被异或了多少次。如果d被异或了奇数次,则异或到答案(ans^=d),否则答案不变。(为什么?因为两个相同的数异或一下就没了!)那么,d被算了多少次呢?因为每连续d个数就有一个d的倍数,所以总共被算了 次。
没优化的代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
void Calc(int x)
{
int ans=0;
for(int d=1;d<=x;d++)
{
if ((x/d)&1)
{
ans^=d;
}
}
printf("%lld\n",ans);
}
main()
{
int n;scanf("%lld",&n);
Calc(n);
return 0;
}
但这样仍然是 的。。。因为我们还要从1~n枚举d
但我们发现n/d有很多是一样的,所以尻♂虑打整除分块。如如果我们能O(1)求1~x的异或和(设为XorSum),则l ~ r的异或和就是
^
,然后就珂以跑整除分块了。快速求1 ~x的异或和的方法珂以上网找博客看看或者自己打表找规律( 反正就是能求 )。然后这个题目就做出来了。
代码:
#include<bits/stdc++.h>
#define int long long//记得开long long
using namespace std;
int XorSum(int x)//求1~x的异或和
{
//你会发现:1~x的异或和是4个一周期的
int t=x&3;//相当于t=x%4
if (t&1) return (t>>1)^1;//t&1相当于t%2==1
else return (t>>1)^x;
}
int RangeSum(int l,int r)//求l~r的异或和
{
return XorSum(r)^XorSum(l-1);
}
void Calc(int x)
{
int ans=0;
for(int l=1,r;l<=x;l=r+1)//整除分块
{
r=x/(x/l);
if ((x/l)&1)//如果是奇数
{
ans^=RangeSum(l,r);//就异或到答案
}
}
printf("%lld\n",ans);
}
main()
{
int n;scanf("%lld",&n);
Calc(n);
return 0;
}
//这么浪只能C++11