0%

2025牛客WC1-J-硝基甲苯之袭

思路讲解

赛时最后30min过了,通过网上搜到的结论,

gcd(a,b)=a xor b=ab(结论,下面是推理过程)gcd(a,b)=a\ xor\ b=a-b(结论,下面是推理过程)

ab<=a xor b=gcd(a,b)a-b<=a\ xor\ b=gcd(a,b)

gcd(a,b)x=a, gcd(a,b)y=b可得ab=(xy)gcd(a,b)可得ab<=gcd(a,b)又因为ab>=gcd(a,b)gcd(a,b)=abgcd(a,b)*x=a,\ gcd(a,b)*y=b\xrightarrow{可得}a-b=(x-y)*gcd(a,b)\xrightarrow{可得}\\a-b<=gcd(a,b)\xrightarrow{又因为a-b>=gcd(a,b)}gcd(a,b)=a-b

当然不可能每题都用结论嘛,所以看看枚举可不可以过

搞半天发现和我的赛时代码也差不多,jiangly差不多也是我这个做法

最重要的其实就是更换枚举尺度,枚举a太慢了,可以枚举g,进而枚举a时只用枚举g的倍数就行了

AC代码

AC

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=74967799

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef array<ll,3> arr;
const ll MAXN=static_cast<ll>(2e5)+10;
ll N,A[MAXN];
ll Cnt[MAXN];
ll gcd(ll a,ll b) {
if(b==0) return a;
return gcd(b,a%b);
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>N;
for(int i=1;i<=N;++i) {
cin>>A[i];
Cnt[A[i]]+=1;
}
// sort(&A[1],&A[N+1]);
ll ans=0;ll m=*max_element(&A[1],&A[N+1]);
for(int g=1;g<=m;++g) {
// 枚举公因数g
for(int a=g;a<=m;a+=g) {
// 枚举a
ll b=a^g;// 判断a,b,g是否符合条件
if(a<b && gcd(a,b)==g && b<=m) {
ans+=Cnt[a]*Cnt[b];
}
}
}
cout<<ans<<endl;
return 0;
}
/*
15
1 1 4 6 6 9 9 8 8 6 7 6 22 26 28

*/

赛时AC记录

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=74946535

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef array<ll,3> arr;
const ll MAXN=static_cast<ll>(2e5)+10;
ll N,T,A[MAXN];
ll gcd(ll a,ll b) {
if(b==0) return a;
return gcd(b,a%b);
}
inline ll lowbit(ll x) {
return x&(-x);
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>N;
for(int i=1;i<=N;++i) {
cin>>A[i];
}
sort(&A[1],&A[N+1]);
ll ans=0;
for(int i=1;i<=A[N];++i) {
for(int j=i;j<=A[N]-i;j+=i) {
if((j^(j+i))!=i) continue;
ans+=(upper_bound(&A[1],&A[N+1],j)-&A[0]-(lower_bound(&A[1],&A[N+1],j)-&A[0])) *
(upper_bound(&A[1],&A[N+1],j+i)-&A[0]-(lower_bound(&A[1],&A[N+1],j+i)-&A[0]));
}
}
cout<<ans<<endl;
return 0;
}
/*
7
1 2 3 4 5 6 7

5
2 6 2 3 4
AC
*/

心路历程(WA,TLE,MLE……)