CF 1603 D Artistic Partition
CF 1603 D Artistic Partition
首先\(k>\log_2n\),答案为\(n\)。
先考虑函数\(C(l,r)\)如何计算:
\[C(l,r)=(\sum_{i\geq l}\sum_{l\leq x<y\leq r}[\gcd(i,j)=l])+r-l+1\\
C(l,r)=(\sum_{i\geq l}G(\lfloor \frac{r}{i}\rfloor))+r-l+1
\]
其中\(G(i)\)表示从\(1,2,...i\)中选出两个不同的数,满足他们的gcd为1。
可以发现\(G(i)=\sum_{j=2}^i\varphi(i)\)。
然后下取整可以用整除分块优化。
预处理\(C\)为\(O(N\sqrt N)\),查询可以二分/哈希,时间复杂度为\(O(\log_2n)/O(1)\)。
然后观察到\(C(l,r)\)满足四边形不等式,所以可以分治优化。
总时间复杂度为\(O(n\log_2^3n+n\sqrt n)/O(n\log_2^2n+n\sqrt n)\) 。
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define rep(a,b) for(int a=0;a<b;++a)
#define LL long long
#define PB push_back
#define POB pop_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
const int bound=100000;
int p[bound+1];
int m[bound+1];
bool v[bound+1];
int pri[bound+1];
void xxs(){
int tot=0;
m[1]=p[1]=1;
rb(i,2,bound){
if(!v[i]){
pri[++tot]=i;
m[i]=-1;
p[i]=i-1;
}
rb(j,1,tot){
if(i>bound/pri[j]) break;
v[i*pri[j]]=1;
if(i%pri[j]){
p[i*pri[j]]=p[i]*(pri[j]-1);
m[i*pri[j]]=-m[i];
}
else{
p[i*pri[j]]=p[i]*pri[j];
m[i*pri[j]]=0;
break;
}
}
}
}
vector<mp> sqrtdivide(int x){
// return the segment [li,ri],where x/li = x/ri
// in O (x^(0.5))
vector<mp> ans;
int sqt=1;
for(int i=1;i*i<=x;i++){
sqt=i;
ans.PB(II(i,i));
}
rl(i,sqt,1){
int l,r;
r=x/i;
l=ceil(x/(i+1)+1e-9);
check_max(l,sqt+1);
if(l<=r)
ans.PB(II(l,r));
}
return ans;
}
LL pre[bound+1];
pair<mp,LL> prefixsum[bound+1][640];
int siz[bound+1];
LL c(int l,int r){
LL ans=r-l+1;
auto Tmp=lower_bound(prefixsum[r],prefixsum[r]+siz[r],II(II(l,INF),(LL)(1e18)));
Tmp=prev(Tmp);
ans+=prefixsum[r][siz[r]-1].SEC;
ans-=Tmp->SEC;
int R=Tmp->FIR.SEC;
ans+=1ll*pre[r/Tmp->FIR.FIR]*(R-l+1);
return ans;
}
LL dp[100000+10][30];
void trans(int a,int b,int l,int r,int j){
if(a>b) return ;
int mid=(a+b)/2;
int p=1;
LL val=1e18;
rb(i,l,min(r,mid)){
LL tmp=c(i,mid)+dp[i-1][j-1];
if(tmp<val){
tie(p,val)=II(i,tmp);
}
}
dp[mid][j]=val;
trans(a,mid-1,l,p,j);
trans(mid+1,b,p,r,j);
}
int main(){
xxs();
p[1]=0;
rb(i,1,bound) pre[i]=pre[i-1]+p[i];
rb(i,1,bound){
auto tmp=sqrtdivide(i);
siz[i]=tmp.size();
rep(j,tmp.size()){
LL val=0;
if(j) val=prefixsum[i][j-1].SEC;
val+=1ll*(tmp[j].SEC-tmp[j].FIR+1)*pre[i/tmp[j].FIR];
prefixsum[i][j]=II(tmp[j],val);
}
}
rb(i,0,100000) rb(j,1,29) dp[i][j]=1e18;
rb(i,1,100000) dp[i][1]=c(1,i);
rb(j,2,29) trans(1,100000,1,100000,j);
int t;
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
if(k>=30){
printf("%d\n",n);
}
else{
printf("%lld\n",dp[n][k]);
}
}
return 0;
}

浙公网安备 33010602011771号