Aug 27

这次的题唐完了,尤其是 T1。

再也不死磕难题了......

T1

给定一个 \(n\)

求解 \(\sum_{a=1}^{n}\sum_{b=a+1}^{n} [gcd(a,b)=a\oplus b]\)

\(n \le 10^7\)

为什么说这个题唐呢?因为它是 \(O(nlogn)\) 的,这个数据范围.....

先说说我的错误解法。

\(gcd(a,b)=c\),因为写起来方便一些。

我们发现 \(a\oplus b=c\) 可得 \(a\oplus c=b\)

因为 \(c\)\(a\) 的约数,我们可以 \(nlogn\) 枚举,这个应该没人不会了。

然后枚举出来后算出 \(b\) 就行。

这个我当时以为是 \(nlogn\) 的,因为我太信任我的 gcd 板子了。

这个板子不是一般的板子,它是硬生生干过基于值域预处理的gcd。

所以平常我看它特别快,就把它当成 \(O(1)\) 的了。

但这道题时间极其极限,稍微多一点常数就会死。

所以这边也是 60 分遗憾离场了。

其实我本来就是冲着这个 60 pts 打的,谁想得到正解就是 \(nlogn\) 啊。

那我们该怎么办???

开始推式子,总体思路是不使用这个 gcd,也就是用一个 \(a,b\) 的其他式子表示出来 \(c\)

反正我是没能想出来的。

众所周知,为什么异或的 latex 是 oplus?因为这个东西不就是一个不进位的加法么。

\(a-b\le a\oplus b=c\)

\(a=k_1*c, b=k_2*c\)

\(a-b=(k_1-k_2)*c\)

\(a-b>=c\)

有因为 \(a-b\le c\)

所以 \(a-b=c=a\oplus b\)

这个判断是 \(O(1)\) 的。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MN=1e7+117;
int ans[MN+1];
int main(){
	freopen("gcdxor.in","r",stdin);
	freopen("gcdxor.out","w",stdout);
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	for(int i=1; i<=MN/2; ++i){
		for(int j=i+i; j<=MN; j+=i){
			if((i^j)==j-i) ans[j]++;
		}
	}
	for(int i=1; i<=MN; ++i) ans[i+1]+=ans[i];
	int val; cin>>val; cout<<ans[val]<<'\n';
	/*
	int T, cnttt=0; cin>>T; while(T--){
		int val; cin>>val;
		cout<<"Case "<<++cnttt<<": "<<ans[val]<<'\n';
	}
	*/
	return 0;
}
posted @ 2025-08-27 15:11  BaiBaiShaFeng  阅读(16)  评论(1)    收藏  举报
Sakana Widget右下角定位