核桃NOI周赛56 varphi
我们首先要知道一个结论,设 \(d=\gcd(a,b)\),则有:\(\varphi(a\times b)=\dfrac{\varphi(a)\times \varphi(b)\times d}{\varphi(d)}\)。
我们不难想到枚举 \(d\) 进行计算。
但是我们会发现一个问题,就是在所有 \(d\) 的倍数中,选出两个数的 \(\gcd\) 只能保证时 \(d\) 的倍数,不能保证一定是 \(d\)。
这里又有一个结论:\(\dfrac{d}{\varphi(d)}\le \dfrac{k\times d}{\varphi(k\times d)}\),也就是说,如果我们强制认为每对数的 \(\gcd\) 都是 \(d\),答案一定不会被算大。
现在我们有一个做法,对于每组询问枚举 \(d\),找出 \(\varphi\) 最大的两个计算贡献(注意这里不论实际 \(\gcd\) 是多少,我们都认为是 \(d\))。
但是这个做法还是太慢了,我们考虑优化。
注意到,如果 \((x,y)\) 是 \([x,y]\) 中最大的贡献的话,一定不存在 \(z\),使得 \(\varphi(z)>max(\varphi(x),\varphi(y))\),否则我们用 \(z\) 匹配上 \(x,y\) 中 \(\varphi\) 大的那一个一定更优。
这样我们可能贡献的对数就很少了,可以直接把询问离线下来然后对 \(l\) 从大到小扫描线,再用一个线段树维护一下当前合法区间内贡献最大值即可。
AC code:
#include<bits/stdc++.h>
#define int long long
#define N 500005
#define pii pair<int,int>
#define x first
#define y second
#define mod 1000000007
#define inf 2e18
using namespace std;
int T=1,n,Q,a[N],phi[N],pre[N],cnt,pos[N],res[N];
bool st[N];
vector<pii>v[N];
struct node{
int l,r,id;
}q[N];
void init(){
phi[1]=1;
for(int i=2;i<N;i++){
if(!st[i]){
pre[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&pre[j]*i<N;j++){
st[pre[j]*i]=1;
if(i%pre[j]==0){
phi[i*pre[j]]=phi[i]*pre[j];
break;
}
phi[i*pre[j]]=phi[i]*(pre[j]-1);
}
}
}
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
struct sgt{
int tr[N<<2];
void pushup(int u){
tr[u]=max(tr[u<<1],tr[u<<1|1]);
}
void modify(int u,int l,int r,int p,int v){
if(l==r){
tr[u]=max(tr[u],v);
return;
}
int mid=l+r>>1;
if(p<=mid)modify(u<<1,l,mid,p,v);
else modify(u<<1|1,mid+1,r,p,v);
pushup(u);
}
int qry(int u,int l,int r,int L,int R){
if(l>=L&&r<=R)return tr[u];
int mid=l+r>>1;
int res=0;
if(L<=mid)res=max(res,qry(u<<1,l,mid,L,R));
if(R>mid)res=max(res,qry(u<<1|1,mid+1,r,L,R));
return res;
}
}sgt;
void solve(int cs){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
pos[a[i]]=i;
}
cin>>Q;
for(int d=1;d<=n;d++){
vector<int>e;
for(int i=d;i<=n;i+=d){
e.push_back(pos[i]);
}
sort(e.begin(),e.end());
stack<int>stk;
for(int i=0;i<e.size();i++){
while(!stk.empty()&&phi[a[e[stk.top()]]]<phi[a[e[i]]])stk.pop();
if(!stk.empty()){
v[e[stk.top()]].push_back({e[i],phi[a[e[stk.top()]]]*phi[a[e[i]]]*d/phi[d]});
}
stk.push(i);
}
while(!stk.empty())stk.pop();
reverse(e.begin(),e.end());
for(int i=0;i<e.size();i++){
while(!stk.empty()&&phi[a[e[stk.top()]]]<phi[a[e[i]]])stk.pop();
if(!stk.empty()){
v[e[i]].push_back({e[stk.top()],phi[a[e[stk.top()]]]*phi[a[e[i]]]*d/phi[d]});
}
stk.push(i);
}
}
for(int i=1;i<=Q;i++){
cin>>q[i].l>>q[i].r;
q[i].id=i;
}
sort(q+1,q+Q+1,[&](node x,node y){
return x.l>y.l;
});
int las=n+1;
for(int k=1;k<=Q;k++){
for(int i=q[k].l;i<las;i++){
for(auto it:v[i]){
sgt.modify(1,1,n,it.x,it.y);
}
}
las=q[k].l;
res[q[k].id]=sgt.qry(1,1,n,q[k].l,q[k].r);
}
for(int i=1;i<=Q;i++){
cout<<res[i]<<'\n';
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// cin>>T;
init();
for(int cs=1;cs<=T;cs++){
solve(cs);
}
return 0;
}

浙公网安备 33010602011771号