洛谷 P10031 题解

题目大意

求出 ⨁ i = 1 n gcd ⁡ ( i , n ) \bigoplus\limits_{i=1}^{n} \gcd(i,n) i=1ngcd(i,n) 的值。

题目解法

前置知识:

  1. 两个相同的数按位异或的结果是 0 0 0,即 a ⊕ a = 0 a \oplus a=0 aa=0
  2. 一个非 0 0 0 的数按位异或 0 0 0 的结果还是原来那个数,即 0 ⊕ a = a 0 \oplus a =a 0a=a
  3. 按位运算遵循交换律,即 a ⊕ b ⊕ c = a ⊕ c ⊕ b a \oplus b \oplus c=a \oplus c \oplus b abc=acb

刚开始一看,想到了暴力。但是发现 n ≤ 1 0 18 n \le 10^{18} n1018,我就知道这题目大概率是一个结论题。但是我没有思路,于是就用暴力打了一个表。

#include<bits/stdc++.h>
using namespace std;
int main(){
	for(int n=1;n<=1000;n++){
		int ans=0;
		for(int i=1;i<=n;i++) ans^=__gcd(i,n);
		cout<<n<<":"<<ans<<"\n";
	}
} 

之后就很容易发现,当 n n n 为奇数时,结果就是 n n n

这是为什么呢?这里用到了欧几里得算法,证明过程我就不写了,详情可以自行查看。

结论就是: gcd ⁡ ( a , b ) = gcd ⁡ ( b − a , b ) \gcd(a,b) = \gcd(b-a,b) gcd(a,b)=gcd(ba,b),也就是 gcd ⁡ ( i , n ) = gcd ⁡ ( n − i , n ) \gcd(i,n) = \gcd(n-i,n) gcd(i,n)=gcd(ni,n)

因此,我们可以发现:

  • n n n 为奇数时,由 a ⊕ a = 0 a \oplus a=0 aa=0 可以得出,前 n − 1 n-1 n1 项会互相抵消(第 i i i 项和第 n − i n-i ni 项抵消),最后只剩下第 n n n 项了,答案就是 0 ⊕ gcd ⁡ ( n , n ) 0 \oplus \gcd(n,n) 0gcd(n,n),由于 0 ⊕ a = a 0 \oplus a=a 0a=a 以及 gcd ⁡ ( a , a ) = a \gcd(a,a)=a gcd(a,a)=a 我们可以得出答案就是 n n n

  • n n n 为偶数时,我们可以发现,前 n 2 − 1 \dfrac{n}{2}-1 2n1 项和第 n 2 + 1 ∼ n − 1 \dfrac{n}{2}+1 \sim n-1 2n+1n1 项可以互相抵消,剩下的第 n 2 \dfrac{n}{2} 2n 项和第 n n n 项按位异或就是答案了。

参考代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
	int t,n;
	cin>>t ;
	while(t--){
		cin>>n;
		if(n%2!=0) cout<<n<<endl;
		else cout<<(n/2^n)<<endl;
	}
} 

2024年第一篇题解,祝大家新年快乐!

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值