A.平方数
讨论一下最接近它的两个平方数即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{IO;int T=1;//cin>>T;while(T--){ll x;cin>>x;ll y=sqrt(x);ll z=y+1;z*=z;y*=y;if(abs(y-x)<abs(z-x)) cout<<y<<'\n';else cout<<z<<'\n';}return 0;
}
B.异或图
首先我们要知道一个性质x⊕x=0x\oplus x=0x⊕x=0
设起点为sss,终点为ttt,如果存在一条路径s−>p1−>p2−>pi−>es->p_1->p_2->p_i->es−>p1−>p2−>pi−>e那么说明有以下等式a[s]⊕a[p1]=ka[p1]⊕a[p2]=ka[p2]⊕a[pi]=ka[pi]⊕a[t]=ka[s]\oplus a[p_1]=k \\ a[p_1]\oplus a[p_2]=k \\a[p_2]\oplus a[p_i]=k\\ a[p_i]\oplus a[t]=ka[s]⊕a[p1]=ka[p1]⊕a[p2]=ka[p2]⊕a[pi]=ka[pi]⊕a[t]=k我们不难发现如果有一条路径能够使得s−>⋯−>ts->\dots->ts−>⋯−>t说明a[s]⊕a[e]=0/ka[s] \oplus a[e]=0/ka[s]⊕a[e]=0/k,并且明显如果a[s]⊕a[e]=ka[s] \oplus a[e]=ka[s]⊕a[e]=k答案是111,如果a[s]⊕a[e]=0a[s] \oplus a[e]=0a[s]⊕a[e]=0需要判断是否有中间点即a[e]⊕ka[e]\oplus ka[e]⊕k是否存在即可,如存在答案是222,否则不存在路径答案是−1-1−1
刚开始以为2202^{20}220很大数组开不下,用unordered_map
存的个数,结果一直T,最后发现数组能开下直接就A了。~。·
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1100010;
int a[N],cnt[N];
int n,q;
int main()
{scanf("%d%d",&n,&q);for(int i=1;i<=n;i++){scanf("%d",&a[i]);cnt[a[i]]++;}while(q--){int k,st,ed;scanf("%d%d%d",&k,&st,&ed);if((a[st]^a[ed])==k) printf("1\n");else{int x=a[st]^k,y=a[ed]^k;if(x!=y||!cnt[x]) printf("-1\n");else printf("2\n");}}return 0;
}
C.公因子
辗转相除法扩展可得以下式子,然后不难乱搞求解
gcd(a1,a2,a3,…,an)=gcd(a1,a2−a1,a3−a2,…,an−an−1)gcd(a_1,a_2,a_3,\dots,a_n)=gcd(a_1,a_2-a_1,a_3-a_2,\dots,a_n-a_{n-1})gcd(a1,a2,a3,…,an)=gcd(a1,a2−a1,a3−a2,…,an−an−1)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1100010;
ll a[N];
int n;
ll gcd(ll a,ll b)
{return b?gcd(b,a%b):a;
}
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+1+n);ll d=a[2]-a[1];for(int i=3;i<=n;i++) d=gcd(d,a[i]-a[i-1]);if(d<0) d=-d;ll res=abs(a[1]/d*d-a[1]);cout<<d<<' '<<res<<'\n';}return 0;
}
E.骚区间
参考大佬题解
一般这种区间左右端点都不确定的情况,我们尝试固定一段点,求另一个端点的可行范围。
对于i
位置作为左端点,考虑如何求右端点的合法区间,由于a[i]
是第二小值,在[i+1,n]
范围内第一个小于a[i]
的位置是l1
,在[i+1,n]
范围内第二个小于a[i]
的位置是r1
,不难看出对于[l1,r1)
范围满足左区间限制条件。
对于i
位置作为右端点,我们同样可以如法炮制的求出满足右端点限制条件的区间(l2,r2]
。
我们可以维护一个树状数组差分求得答案。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1000010;
int a[N],n;
struct node
{int l,r;int mx,mn;
}tree[N*4];
void pushup(int u)
{tree[u].mx=max(tree[u<<1].mx,tree[u<<1|1].mx);tree[u].mn=min(tree[u<<1].mn,tree[u<<1|1].mn);
}
void build(int u,int l,int r)
{tree[u]={l,r,0,n+1};if(l==r){tree[u].mx=tree[u].mn=a[l];return;}int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(u);
}
int query_min(int u,int l,int r,int x)
{if(l>r) return n+1;if(tree[u].mn>=x) return n+1;if(tree[u].l==tree[u].r) return tree[u].l;int mid=tree[u].l+tree[u].r>>1;if(l>mid) return query_min(u<<1|1,l,r,x);else if(r<=mid) return query_min(u<<1,l,r,x);else{if(tree[u<<1].mn<x){int v=query_min(u<<1,l,r,x);return v!=n+1?v:query_min(u<<1|1,l,r,x);}elsereturn query_min(u<<1|1,l,r,x);}
}
int query_max(int u,int l,int r,int x)
{if(l>r) return 0;if(tree[u].mx<=x) return 0;if(tree[u].l==tree[u].r) return tree[u].l;int mid=tree[u].l+tree[u].r>>1;if(l>mid) return query_max(u<<1|1,l,r,x);else if(r<=mid) return query_max(u<<1,l,r,x);else{if(tree[u<<1|1].mx>x) {int v=query_max(u<<1|1,l,r,x);return v?v:query_max(u<<1,l,r,x);}else return query_max(u<<1,l,r,x);}
}
vector<int> p[N];
int cnt[N];
int lowbit(int x)
{return x&-x;
}
void update(int k,int x)
{for(;k<=n;k+=lowbit(k)) cnt[k]+=x;
}
ll query(int k)
{ll now=0;for(;k;k-=lowbit(k)) now+=cnt[k];return now;
}
int main()
{int T=1;//cin>>T;while(T--){scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);build(1,1,n);ll res=0;for(int i=1;i<=n;i++){int l=query_min(1,i+1,n,a[i]);int r=query_min(1,l+1,n,a[i]);if(l!=n+1) p[l].push_back(i);if(r!=n+1) p[r].push_back(-i);for(auto t:p[i]){if(t>0) update(t,1);else update(-t,-1);}r=query_max(1,1,i-1,a[i]);l=query_max(1,1,r-1,a[i]);res+=query(r)-query(l);}printf("%lld\n",res);}return 0;
}
要加油哦~