IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> [CF1603D]Artistic Partition -> 正文阅读

[游戏开发][CF1603D]Artistic Partition

Artistic Partition

题解

看到这种统计最小值的题应该很容易想到 d p dp dp,我们可以记 d p i , j dp_{i,j} dpi,j?表示划分到点 i i i,已经划分了 j j j块,但如果直接进行 d p dp dp转移的话显然会 T T T
但我们可以猜测到一点,当 K K K比较大的时候,我们应该很容易划分这个序列使得每个数在其区间中,与除自己外的所有数的 gcd ? \gcd gcd都不大于改区间的 l l l
也就是说我的的答案就为 n n n
有了这个结论,我们就可以去想想怎么划分。
一个区间 [ l , r ] [l,r] [l,r]第一个会使得 gcd ? ( l , r ) ? l \gcd(l,r)\geqslant l gcd(l,r)?l的数对显然是 ( l , 2 l ) (l,2l) (l,2l),也就是说,如果我们的 r < 2 l r< 2l r<2l,改区间答案便为 r ? l + 1 r-l+1 r?l+1
容易发现,这样的话,只要我们的 2 k > n 2^k>n 2k>n,就答案就为 n n n。也就是说,我们需要 d p dp dp K K K log ? n \log n logn级别的,我们的总状态数是 n log ? n n\log n nlogn级别。

我们的状态数大概无法继续优化了,但我们的 d p dp dp转移是可继续优化的。
我们用 c ( l , r ) c(l,r) c(l,r)表示将区间 [ l , r ] [l,r] [l,r]划分一段所产生的贡献,则转移式为:
d p i , k = min ? j = 0 i ? 1 ( d p j , k ? 1 + c ( j + 1 , i ) ) dp_{i,k}=\min_{j=0}^{i-1}\left(dp_{j,k-1}+c(j+1,i)\right) dpi,k?=j=0mini?1?(dpj,k?1?+c(j+1,i))显然,这个 d p dp dp转移是单调的,对于 k k k相同的 d p dp dp,显然我 i i i越大,我们的划分点就会继续右移。
事实上,我们可以通过说明对于 l < l ′ < r ′ < r l<l'<r'<r l<l<r<r,有 c ( l , r ) + c ( l ′ , r ′ ) ? c ( l , r ′ ) + c ( l ′ , r ) c(l,r)+c(l',r')\geqslant c(l,r')+c(l',r) c(l,r)+c(l,r)?c(l,r)+c(l,r)来证明它的单调性。
而这个式子显然是成立的,前面的部分比后面多了区间 [ l , l ′ ) [l,l') [l,l)与区间 ( r ′ , r ] (r',r] (r,r]间的贡献。
这样的话,我们就可以用分治优化我们的 d p dp dp转移了。

但无论怎么转移,我们都需要快速求出我们的 c ( l , r ) c(l,r) c(l,r)呀。
推一推 c c c的式子。
c ( l , r ) = ∑ i = l r ∑ j = i r [ ( i , j ) ? l ] = ∑ d = l r ∑ i = l r ∑ j = i r [ ( i , j ) = d ] = ∑ d = l r ∑ i = 1 ? r d ? ∑ j = 1 i [ ( i , j ) = 1 ] = ∑ d = l r ∑ i = 1 ? r d ? φ ( i ) = ∑ d = l r s ( r d ) c(l,r)=\sum_{i=l}^{r}\sum_{j=i}^{r}[(i,j)\geqslant l]=\sum_{d=l}^{r}\sum_{i=l}^{r}\sum_{j=i}^{r}[(i,j)=d]\\ =\sum_{d=l}^{r}\sum_{i=1}^{\lfloor\frac{r}{d}\rfloor}\sum_{j=1}^{i}[(i,j)=1]=\sum_{d=l}^{r}\sum_{i=1}^{\lfloor\frac{r}{d}\rfloor}\varphi(i)=\sum_{d=l}^{r}s(\frac{r}{d}) c(l,r)=i=lr?j=ir?[(i,j)?l]=d=lr?i=lr?j=ir?[(i,j)=d]=d=lr?i=1?dr???j=1i?[(i,j)=1]=d=lr?i=1?dr???φ(i)=d=lr?s(dr?)其中 s ( n ) = ∑ i = 1 n φ ( i ) s(n)=\sum_{i=1}^n\varphi(i) s(n)=i=1n?φ(i),也就是 φ \varphi φ的前缀和。
而这就可以整除分块了,我们可以先预处理一下块的前缀和,每次查询就算一下它所在块后缀和,再加上整块的后缀和就行了。
这样就可以做到预处理 O ( n n ) O\left(n\sqrt n\right) O(nn ?),单次查询 O ( 1 ) O\left(1\right) O(1)
事实上我们可以再将整个 d p dp dp数组都预处理了,然后每次询问就可以 O ( 1 ) O\left(1\right) O(1)回答了。

总时间复杂度 O ( n log ? 2 n + n n ) O\left(n\log^2 n+n\sqrt n\right) O(nlog2n+nn ?)

源码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL; 
typedef long double Ld;
typedef pair<LL,LL> pii;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int mo=998244353;
const int mod=1e6+7;
const int inv2=499122177;
const int inv3=332748118;
const int jzm=2333;
const int zero=2000;
const int n1=100;
const int lim=100000;
const int orG=3,ivG=332748118;
const double Pi=acos(-1.0);
const double feps=1e-11;
const double eps=1e-9;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0)putchar('-'),print(-x);if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;}return t;}
int T,n,K,prime[MAXN],cntp,phi[MAXN];
LL pre[MAXN],dp[MAXN][20],mp1[MAXN][405],mp2[MAXN][405];
int al[MAXN],ar[MAXN],idx;
bool oula[MAXN];
void init(){
	pre[1]=1;
	for(int i=2;i<=n;i++){
		if(!oula[i])prime[++cntp]=i,phi[i]=i-1;
		for(int j=1;j<=cntp&&i*prime[j]<=n;j++){
			oula[i*prime[j]]=1;
			if(i%prime[j]==0){phi[i*prime[j]]=prime[j]*phi[i];continue;}
			else phi[i*prime[j]]=(prime[j]-1)*phi[i];
		}
		pre[i]=pre[i-1]+phi[i];
	}
	for(int i=1;i<=n;i++){
		idx=0;LL summ=0;
		for(int l=1,r;l<=i;l=r+1)
			r=i/(i/l),idx++,al[idx]=l,ar[idx]=r;
		for(int j=idx;j>0;j--){
			summ+=1ll*(ar[j]-al[j]+1)*pre[i/ar[j]];
			if(al[j]<=i/al[j])mp1[i][al[j]]=summ;
			else mp2[i][i/al[j]]=summ;
		}
	}
}
LL work(int L,int R){
	if(L>R)return 0;int r=R/(R/L)+1;
	return 1ll*(r-L)*pre[R/L]+(r<=R/r?mp1[R][r]:mp2[R][R/r]);
}
void sakura(int l,int r,int L,int R,int k){
	int mid=l+r>>1;dp[mid][k]=INF;
	LL tmp=work(R+1,mid);int mk=0;
	for(int i=min(mid,R);i>=L;i--){
		if(dp[i][k-1]+tmp<dp[mid][k])
			dp[mid][k]=dp[i][k-1]+tmp,mk=i;
		if(i&&i<=mid)tmp+=pre[mid/i];
	}
	if(l<mid)sakura(l,mid-1,L,mk,k);
	if(r>mid)sakura(mid+1,r,mk,R,k);
}
int main(){
	read(T);n=100000;K=16;init();
	dp[0][0]=0;for(int i=1;i<=n;i++)dp[i][0]=INF;
	for(int i=1;i<=K;i++)sakura(0,n,0,n,i);
	while(T--){
		read(n);read(K);
		if(K>16||(1<<K)-1>=n){printf("%d\n",n);continue;}
		printf("%lld\n",dp[n][K]);
	}
	return 0;
}

谢谢!!!

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:59:49  更:2022-03-30 19:01:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:29:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码