Codeforces Round #752 D

这篇博客探讨了如何利用欧拉函数的性质和数论分块技术解决计算问题。作者通过预想最优分布并采用动态规划(DP)方法优化复杂度,特别是借助分治DP和决策单调性来降低计算复杂度。文章中还提供了AC代码作为解决方案的实例。
摘要由CSDN通过智能技术生成

首先考察c(l,r):

c\left ( l ,r \right )=\sum_{l\leq i\leq j\leq r}^{} [gcd(i,j)\geq l] \\ =\sum_{l\leq T\leq r}\sum_{l\leq i\leq j \leq r}[gcd(i,j)=T] =\sum_{l \leq T \leq r}\sum_{1 \leq i \leq j \leq \left \lfloor \frac{r}{T} \right \rfloor} [gcd(i,j)=1]\\ =\sum_{l \leq T \leq r} \sum_{1 \leq x \leq \left \lfloor \frac{r}{T} \right \rfloor} \phi(x) =\sum_{l \leq T \leq r} P(\left \lfloor \frac{r}{T} \right \rfloor) \\ ( P( n )=\sum_{1 \leq x \leq n} \phi(x) )

由此可见c(l,r)可以分解为一串欧拉函数值的和,且可以借由前缀和、数论分块的手段 O(n\log n+\sqrt{n})地解决。

再考虑目标min \sum_{1\leq n \leq k} c(x_{n}+1,x_{n+1}),能够预想,最优时,\{x_{n}\}按某种规则均匀分布

并且显然有一个O(n^{2+1/2}k)的DP,我们可以尝试优化它。

回头考虑c(l,r),其中函数P的系数在l \leq T \leq 2l-1时恒为1,也即此时c(l,r)的值与\phi函数分布无关,于是我们发现[1,n]的一个分划[1,1],[2,3],[4,7],[8,15],...[2^{t},n]满足\sum c(x_{n}+1,x_{n+1})=n,于是我们只需考虑\log_{2} (n+1)\geq k的情况。

那么我们可以O(n^{2+1/2})的进行DP,然而这样的复杂度仍然偏高,我们可以尝试优化DP,考虑到目标决策状态具有某种意义上的分布均匀性,我们可以试图证明其决策单调性,四边形不等式是一个不错的选择。

proof:i \leq j \leq k \leq l : c(i,k)+c(j,l) \leq c(i,l)+c(j,k) \\ \Leftrightarrow \sum_{i \leq T \leq k} P(\left \lfloor \frac{k}{T} \right \rfloor) + \sum_{j \leq T \leq l} P(\left \lfloor \frac{l}{T} \right \rfloor) \leq \sum_{i \leq T \leq l} P(\left \lfloor \frac{l}{T} \right \rfloor) + \sum_{j \leq T \leq k} P(\left \lfloor \frac{k}{T} \right \rfloor) \\ \Leftrightarrow \sum_{i \leq T <j} P(\left \lfloor \frac{k}{T} \right \rfloor) \leq \sum_{i \leq T <j} P(\left \lfloor \frac{l}{T} \right \rfloor) \\ \Leftarrow P(\left \lfloor \frac{k}{T} \right \rfloor) \leq P(\left \lfloor \frac{l}{T} \right \rfloor) (i \leq T < j)

所以我们可以用分治DP来优化至O(n^\frac{3}{2}\log_2n)

下附AC代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define MAXN 100010
ll phi[MAXN],P[MAXN];

void totient(){
	P[0]=0,P[1]=1;
	for(int i=0;i<MAXN;++i){
		phi[i]=1;
	}
	for(ll i=2;i<MAXN;++i){
		if(phi[i]==1){
			for(ll j=i;j<MAXN;j*=i){
				for(ll k=j;k<MAXN;k+=j){
					if(j==i){
						phi[k]*=i-1;
					}
					else{
						phi[k]*=i;
					}
				}
			}
		}
		P[i]=P[i-1]+phi[i];
	}
}

const ll inf=1E18;

ll c(int l,int r){
	if(l>r)return inf;
	ll sum=0;
	while(l<=r){
		int pr=r/(r/l);
		if(pr>r)pr=r;
		sum+=(pr-l+1)*P[r/l];
		l=pr+1;
	}
	return sum;
}

ll dp[MAXN][18];
int MIN(int x,int y){
	if(x<y){
		return x;
	}
	return y;
}
void DC_DP(int d,int l,int r,int optl,int optr){
	if(l>r){
		return;
	}
	ll m=(l+r)>>1;
	ll opt=MIN(optr,m);
	ll cost=c(opt+1,m);
	dp[m][d]=inf;
	for(int k=opt;k>=optl;--k){
		ll prc=cost+dp[k][d-1];
		if(dp[m][d]>prc){
			dp[m][d]=prc;
			opt=k;
		}
		if(cost==inf){
			cost=c(k,m);//for next
		}
		else{
			cost+=P[m/k];
		}
	}
	DC_DP(d,l,m-1,optl,opt);
	DC_DP(d,m+1,r,opt,optr);
}

int main(){
	int T,n,k;
	scanf("%d",&T);
	totient();
	n=100000;
	k=17;
	for(int i=0;i<=n;++i){
		dp[i][1]=c(1,i);
	}
	for(int i=2;i<=k;++i){
		DC_DP(i,1,n,1,n);
	}
	while(T--){
		scanf("%d%d",&n,&k);
		if((k>=18)||((1<<k)>n)){
			printf("%d\n",n);
			continue;
		}
		printf("%lld\n",dp[n][k]);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值