D - Together Square
题意:
计算有对少对小于等于
n
(
1
≤
n
≤
2
×
1
0
5
)
n(1 \leq n \leq 2×10^5)
n(1≤n≤2×105)的
i
,
j
i,j
i,j,满足
i
×
j
i×j
i×j是平方数
思路:
如果
i
i
i是平方数,那么
j
j
j也是平方数才行。
否则,
j
j
j应该是平方数乘以
i
i
i中出现次数为奇数的质因子
#include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int,int> PII;
const int maxn=2e5+7;
int n,vis[maxn];
int main()
{
scanf("%d",&n);
vector<int>v;
for(int i=1;;i++)
{
if(i*i>n) break;
vis[i*i]=1;v.pb(i*i);
}
ll ans=0;
for(int i=1;i<=n;i++)
{
if(vis[i]) ans+=v.size();
else
{
int nn=i;
for(int j=1;j<v.size();j++)
{
while(nn%v[j]==0)
{
nn/=v[j];
}
}
for(int j=0;j<v.size();j++)
{
if(v[j]*nn>n) break;
ans++;
}
}
}
printf("%lld\n",ans);
}
F - Rectangle GCD
题意:
有长度为
n
(
1
≤
n
≤
2
×
1
0
5
)
n(1≤n≤2×10^5)
n(1≤n≤2×105)的数组
A
,
B
(
1
≤
A
i
,
B
i
≤
1
0
9
)
A,B(1≤A _i,B_i≤10^9)
A,B(1≤Ai,Bi≤109),以及一个
n
×
n
n×n
n×n的正方形,第
i
i
i行第
j
j
j列的数为
A
i
+
B
j
A_i+B_j
Ai+Bj
有
q
(
1
≤
q
≤
2
×
1
0
5
)
q(1≤q≤2×10^5)
q(1≤q≤2×105)次询问,每次询问一个矩形区域内所有数字的
gcd
\gcd
gcd
思路:
矩形内数字为
a
i
+
b
j
a
i
+
b
j
+
1
a
i
+
b
j
+
2
a
i
+
b
j
+
3
.
.
.
a
i
+
1
+
b
j
a
i
+
1
+
b
j
+
1
a
i
+
1
+
b
j
+
3
a
i
+
1
+
b
j
+
2
.
.
.
.
.
.
.
.
.
a_i+b_j \quad a_{i}+b_{j+1} \quad a_{i}+b_{j+2} \quad a_{i}+b_{j+3} \quad ...\\ a_{i+1}+b_{j} \quad a_{i+1}+b_{j+1} \quad a_{i+1}+b_{j+3} \quad a_{i+1}+b_{j+2} \quad ...\\ ......
ai+bjai+bj+1ai+bj+2ai+bj+3...ai+1+bjai+1+bj+1ai+1+bj+3ai+1+bj+2.........
已知性质
gcd
(
a
,
b
,
c
,
d
)
=
gcd
(
a
,
b
−
a
,
c
−
b
,
d
−
c
)
\gcd(a,b,c,d)=\gcd(a,b-a,c-b,d-c)
gcd(a,b,c,d)=gcd(a,b−a,c−b,d−c)
所以问题转化为
gcd
\gcd
gcd数组
B
,
A
B,A
B,A的差分数组
用线段树维护即可
#include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int,int> PII;
const int maxn=2e5+7;
struct gcd_tree
{
int nums[maxn];
struct tree
{
int l,r,sum;
int mid()
{
return (l+r)/2;
}
}tre[maxn<<2];
void pushup(int num)
{
tre[num].sum=__gcd(tre[2*num].sum,tre[2*num+1].sum);
}
void build(int num,int l,int r)
{
tre[num].l=l,tre[num].r=r;
if(l==r)
{
tre[num].sum=nums[l];return;
}
int mid=tre[num].mid();
build(2*num,l,mid);
build(2*num+1,mid+1,r);
pushup(num);
}
int query(int num,int l,int r)
{
if(tre[num].l==l && tre[num].r==r)
return tre[num].sum;
int mid=tre[num].mid();
if(l>mid)
return query(2*num+1,l,r);
else if(r<=mid)
return query(2*num,l,r);
else
return __gcd(query(2*num,l,mid),query(2*num+1,mid+1,r));
}
}da,db;
int n,m;
int a[maxn],b[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++) da.nums[i]=abs(a[i]-a[i-1]);
da.build(1,1,n);
for(int i=1;i<=n;i++) db.nums[i]=abs(b[i]-b[i-1]);
db.build(1,1,n);
while(m--)
{
int h1,h2,w1,w2;scanf("%d%d%d%d",&h1,&h2,&w1,&w2);
int ans=a[h1]+b[w1];
if(h2>h1) ans=__gcd(ans,da.query(1,h1+1,h2));
if(w2>w1) ans=__gcd(ans,db.query(1,w1+1,w2));
printf("%d\n",ans);
}
}