比赛地址
A.平方数
思路:暴力打表
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll a[N];
void get_sqrt(int n)
{
for(ll i=1;i<=n;i++)a[i]=i*i;
}
int main()
{
ll x,y=0;
scanf("%lld",&x);
get_sqrt(1e6+3);
for(int i=1;i<=x;i++){
if(abs(y-x)>abs(a[i]-x))y=a[i];
else break;
}
printf("%lld\n",y);
return 0;
}
B 异或图
思路:每次输入k,x,y时异或一下x和y节点对应的点权,判断是否与k相等,相等则直接输出-1,否则继续判断,看这个图中是否存在中介点使得x和y节点可以互相到达,即利用异或性质判断k^x以后所得的结果是否在点集中,在则输出2,否则输出-1,不存在比2更大的距离,因为假如x和y中间存在多于一个点,比如2个点时,x和点1异或后等于k,点1和点2异或等于k,则点2等于x,其实就是x点,因此,不可能存在大于2的距离,由此只需判断当a[x]==a[y]时用k异或x或者y对应的点权后所得结果是否在这个点集图中,在则存在中介点连接x和y节点,距离为2,否则输出-1
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2*1e6;
int a[N];
bool vis[N];//因为2的20次方是1,048,576
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){scanf("%d",&a[i]);vis[a[i]]=true;}
while(q--){
int k,x,y;
scanf("%d%d%d",&k,&x,&y);
x=a[x],y=a[y];
if((x^y)==k)puts("1");
else if(x==y&&vis[k^x]==true)puts("2");
else puts("-1");
}
return 0;
}
C 公因子
思路:gcd性质的应用
分析:要求a数组同时+x后的gcd,我们先来观察一下数据范围,n<=1e6,数组开到1e6+10足够了,而a的元素范围在正负10的18次方范围内,因此肯定要开longlong,再来观察一下式子的特点,我们发现+x后元素本身大小虽然变了,但是元素之间的差值不变,即ai->ai+x,aj->aj+x,但是(aj+x)-(ai+x)=aj-ai,由此联想到gcd的一条性质gcd(a,b)=gcd(a,b-a),因此,求+x后的a数组的gcd就可以转化成求原数组的差分数组的gcd,这样就不必苦恼没有x不好动手,求出gcd后因为a1+x必然是gcd的倍数,因此直接构造满足条件的x,当x<0时直接构造x=abs(a[1])使得a1+x后变成0,仍然满足a1+x整除gcd,而a1>0时由于数组gcd是通过差值求出来的,即ai-a1要能整除gcd,因此令x=gcd-a1,使得a1+x=a1+gcd-a1–>ai+x=ai+gcd-a1,显然可以使得ai+x整除gcd成立,因此构造成立((ai-a1)%gcd=0,因为gcd就是通过这么得到的,所以这个式子肯定成立,又gcd%gcd==0,所以ai+gcd-a1必然能整除gcd,所以构造成立)(这里构造的差分数组可以构造ai+1-ai这种,也可以ai-a1,固定一个a1作为定点来计算差值,都是可以ac的
ac:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll a[N];
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int n;
scanf("%d",&n);
ll d=0,x;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
sort(a+1,a+n+1);
for(int i=2;i<=n;i++){
d=gcd(d,a[i]-a[1]);//也可以a[i]-a[i-1]
}
if(a[1]<0)x=abs(a[1])%d;
else x=(d-a[1]%d);
printf("%lld %lld\n",d,x);
return 0;
}