题解CF1712E2【LCM Sum (hard version) 】
xuanxuan001 · · 题解
做法不太一样,发篇题解。
赛时居然切了 E1 没切 E2,可能大半夜脑子有点昏。
考虑计算出
设
要满足这个条件,可以分为
如果
如果
最后经尝试(?),
所以刚才经过一大波初(xiao)中(xue)数(ao)学(shu)式的推导后,得出满足条件的
得出了这个比例后我们就可以很容易的求出有多少组满足的了。以第一个比例 3:4:6 为例,设
同理,第二个比例算出来的公式是
重点是
可以反过来考虑,对于每个
对于 E1,可以直接处理
对于 E2,我赛时完全没有想法,考虑了一下主席树,然后空间过大,弃了。
第二天白天准备补一下,在我就要点开 CF 官方题解的那一刻,我突然有了思路:这个直接离线不就行了!
然后推了一小会,通了。
还是前面那个做法,但是正着枚举
发现一个
单点加区间求和是一个裸的树状数组,维护即可。
发现会更新
最终复杂度
代码:
#include<cstdio>
#include<vector>
#define TY ll
#define MAXN 200002
#define MAXM 100002
#define debug if(1==1)
#define FOR(i,a,b) for(TY i=(a);i<=(b);++i)
#define fOR(i,a,b) for(TY i=(a);i<(b);++i)
#define ROF(i,a,b) for(TY i=(a);i>=(b);--i)
#define rOF(i,a,b) for(TY i=(a);i>(b);--i)
using namespace std;
typedef double db;
typedef long long ll;
const TY M=998244353;
typedef unsigned long long ull;
TY _abs(TY a){return a<0?-a:a;}
TY maxn(TY a,TY b){return a>b?a:b;}
TY minn(TY a,TY b){return a<b?a:b;}
TY gcd(TY a,TY b){return b?gcd(b,a%b):a;}
TY qp(TY a,TY b){TY ans=1;do{if(b&1)ans=ans*a%M;a=a*a%M;}while(b>>=1);return ans;}
char getc(){char ch=getchar();while(ch==' '||ch=='\n')ch=getchar();return ch;}
void prtcan(bool x,bool big){
if(x){
if(big)printf("YES\n");
else printf("Yes\n");
}else{
if(big)printf("NO\n");
else printf("No\n");
}
}TY qr(){
char ch=getchar();TY s=0,x=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')x=-1;
for(;ch>='0'&&ch<='9';ch=getchar())s=s*10+ch-'0';return x*s;
}void qw(TY a,char ch){
if(a<0){a=-a;putchar('-');}
if(a>9)qw(a/10,0);putchar(a%10+'0');
if(ch)putchar(ch);
}TY T=qr(),l,r,cnt[MAXN],tre[MAXN],ans[MAXM];vector<TY>id[MAXN],v[MAXN];
TY js(TY a){return a*(a-1)*(a-2)/6;}
TY len(TY l,TY r){return l<=r?r-l+1:0;}
inline void add(TY x,TY d){for(;x<MAXN;x+=x&-x)tre[x]+=d;}
TY ask(TY x){TY s=0;for(;x;x^=x&-x)s+=tre[x];return s;}
int main(){
FOR(i,1,T){
l=qr();r=qr();ans[i]=js(r-l+1);
ans[i]-=len((l+2)/3,r/6);
ans[i]-=len((l+5)/6,r/15);//c不等于1的情况
id[l].push_back(i);v[l].push_back(r);
}ROF(i,MAXN-1,1){
for(TY j=i<<1;j<MAXN;j+=i)add(j,cnt[j]++);//tre维护C(cnt,2)的树状数组
fOR(j,0,id[i].size())ans[id[i][j]]-=ask(v[i][j])-ask(i-1);//c=1的情况考虑
}FOR(i,1,T)qw(ans[i],'\n');
return 0;
}