GCD XOR
Description:
输入一个整数n,有多少对整数(a,b)满足 1≤b≤a≤n,
思路历程:
①暴力循环 时间复杂度O(n^2),毫无疑问会超时。
②考虑到(虽然自己一开始不知道)
,
令c=gcd(a,b),或者 c 必然是a的约数,所以枚举a,c,用 a XOR c算出b,再检验 gcd(a,b)==c。时间复杂度O(nlognlogn)
ps:一开始还想着用vector<int> facotr[]
去存储枚举的a的正约数集合,发现编译都通不过(数组太大了)
但是,这样还是TLE。还是得优化。
③
令
由上面的式子得,,于是还是枚举a,c,用a-b=c算出b,再检验
a XOR b == c。
时间复杂度:O(n*logn)
int t,n;
int ncase=0;
int main(){
cin>>t;
while(t--)
{
ll ans=0;
scanf("%d",&n);
int a,b,c;
for(c=1;c<=n;c++)
{
for(int k=2;k<=n/c;k++)
{
a=k*c;
b=a-c;
if(c==(a^b))
{
ans++;
}
}
}
printf("Case %d: %lld\n",++ncase,ans);
}
return 0;
}
但是,还是TLE!
题目要求测试量可达10000,整体时间复杂度O(Tnlogn)
④依照用空间换时间的想法。
时间复杂度:O(n*logn+T)
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 3e7;
int t,n;
int ncase=0,num[maxn+10];
void init()
{
for(int c=1;c<=maxn/2;c++)
{
for(int a=2*c;a<=maxn;a+=c)
{
if((a^(a-c))==c)
num[a]++;
}
}
for(int i=2;i<=maxn;i++)
num[i]+=num[i-1];
}
int main(){
cin>>t;
init();
while(t--)
{
scanf("%d",&n);
printf("Case %d: %d\n",++ncase,num[n]);
}
return 0;
}
num[n] 一开始存放的是在 a=n 时,满足1≤b≤a 且满足的数对的对数。
当然题目要求的是小于某个数n的数对的个数,也就说
ps:用倍数法枚举正约数
for(int c=1;c<=maxn/2;c++)
{
for(int a=2*c;a<=maxn;a+=c)
{
//...... c是a的约数
}
}
或者
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n/i;j++)
{
//...... i是i*j 的约数
}
}
来源:CSDN
作者:好喜欢萨摩猪
链接:https://blog.csdn.net/qq_44846324/article/details/104502714