[CF1603D] Artistic Partition

题解

问题其实就是要你把 1 ∼ n 1\sim n 1∼n 分成 k k k 段,最小化每一段的 c c c 值的和。

首先我们会想到,如果区间 [ l , r ] [l,r] [l,r] 中不存在两个有倍数关系的数,即 r < 2 l r<2l r<2l,那么 c ( l , r ) c(l,r) c(l,r) 就会取最小值 r − l + 1 r-l+1 r−l+1。

也就是说,如果我们按 [ 1 , 1 ] , [ 2 , 3 ] , [ 4 , 7 ] , [ 8 , 15 ] . . . [1,1],[2,3],[4,7],[8,15]... [1,1],[2,3],[4,7],[8,15]... 这样的方式去分段,那么只需分 log ⁡ n \log n logn 段即可把答案取到最小值 n n n,而且答案关于段数单调不增。

所以我们只需要考虑 k < log ⁡ n k<\log n k<logn 时的答案,这就已经大大减少了状态数,我们可以预处理出所有答案然后 O ( 1 ) O(1) O(1) 查询。

考虑设DP状态 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示把 1 ∼ i 1\sim i 1∼i 分成 j j j 段时的最小答案,转移需要枚举分的最后一段是多少,复杂度不可通过。

考虑加速这个过程,观察式子:
c ( l , r ) = ∑ j = l r ∑ d ≥ l , d ∣ j ∑ i = 1 j d [ gcd ⁡ ( i , j d ) = 1 ] = ∑ j = l r ∑ d ≥ l , d ∣ j φ ( j d ) c(l,r)=\sum_{j=l}^r\sum_{d\ge l,d|j}\sum_{i=1}^{\frac{j}{d}}[\gcd(i,\frac{j}{d})=1]=\sum_{j=l}^r\sum_{d\ge l,d|j}\varphi(\frac{j}{d}) c(l,r)=j=l∑r​d≥l,d∣j∑​i=1∑dj​​[gcd(i,dj​)=1]=j=l∑r​d≥l,d∣j∑​φ(dj​)
我们可以想到用线段树维护最小的DP值,每次枚举 i i i 的因子然后用预处理出的欧拉函数做一个前缀加操作,查询就直接查前缀最小值即可。

这个做法的复杂度是 O ( n log ⁡ 3 n ) O(n\log^3n) O(nlog3n) 的,比正解多一个 l o g log log,但是zkw线段树随便过。

代码

#include<bits/stdc++.h>//JZM yyds!!
#define ll long long
#define uns unsigned
#define IF (it->first)
#define IS (it->second)
#define END putchar('\n')
using namespace std;
const int MAXN=100002;
const ll INF=1e18;
inline ll read(){ll x=0;bool f=1;char s=getchar();while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();return f?x:-x;
}
int ptf[50],lpt;
inline void print(ll x,char c='\n'){if(x<0)putchar('-'),x=-x;ptf[lpt=1]=x%10;while(x>9)x/=10,ptf[++lpt]=x%10;while(lpt)putchar(ptf[lpt--]^48);if(c>0)putchar(c);
}
inline ll lowbit(ll x){return x&-x;}bool nop[MAXN];
int pr[MAXN],le,phi[MAXN];
inline void init(int n){nop[0]=nop[1]=1,phi[1]=1,le=0;for(int a=2;a<=n;a++){if(!nop[a])pr[++le]=a,phi[a]=a-1;for(int i=1,u;i<=le&&(u=pr[i]*a)<=n;i++){nop[u]=1;if(a%pr[i]==0)phi[u]=phi[a]*pr[i],i=le;else phi[u]=phi[a]*(pr[i]-1);}}
}
int n,k;
const int m=17;
ll dp[MAXN][18];
struct zkw{ll f[MAXN*3],lz[MAXN*3];int p;inline void init(int n){for(p=1;p<n+2;p<<=1);for(int i=p+n+2;i>0;i--)f[i]=INF;}inline void cg(int x,ll d){for(f[p+x]=d,x=(p+x)>>1;x;x>>=1)f[x]=min(f[x<<1],f[x<<1|1])+lz[x];}inline void add(int r,ll d){for(r=p+r+1;r>1;){if(r&1)f[r^1]+=d,lz[r^1]+=d;r>>=1,f[r]=min(f[r<<1],f[r<<1|1])+lz[r];}}
}T[17];
vector<int>Z[MAXN];
signed main()
{n=1e5,init(n);memset(dp,0x7f,sizeof(dp));for(int i=0;i<m;i++)T[i].init(n);dp[0][0]=0;for(int i=0;i<m;i++)T[i].cg(1,dp[0][i]);for(int i=1;i<=n;i++)for(int j=i;j<=n;j+=i)Z[j].push_back(i);for(int i=1;i<=n;i++){for(int j=0;(1<<j)<=i;j++)for(int z:Z[i])T[j].add(z,phi[i/z]);for(int j=1;(1<<j)<=i;j++)dp[i][j]=T[j-1].f[1];for(int j=0;(1<<j)<=i+1;j++)T[j].cg(i+1,dp[i][j]);}for(int mudamudamudamudamuda=read();mudamudamudamudamuda--;){n=read(),k=read();if(k>m||(1<<k)>n)print(n);else print(dp[n][k]);}return 0;
}

[CF1603D] Artistic Partition——欧拉函数,线段树优化DP相关推荐

  1. bzoj 5245: [Fjwc2018]欧拉函数 线段树+bitset

    题意 对于正整数 n,定义欧拉函数 φ(n) 为小于等于 n 且与 n 互质的正整数个数.例如 φ(1) = 1, φ(8) = 4. 给定正整数序列 a1, a2, · · · , an,请依次执行 ...

  2. jzoj4638-第三条跑道【欧拉函数,线段树】

    正题 题目大意 要求支持区间乘和区间求∏φ(xi)\prod \varphi(x_i)∏φ(xi​) 解题思路 首先φ(n)=n∗∏(pi−1pi)\varphi(n)=n*\prod (\frac{ ...

  3. [LNOI] 相逢是问候 || 扩展欧拉函数+线段树

    原题为2017六省联考的D1T3 给出一个序列,m次操作,模数p和参数c 操作分为两种: 1.将[l,r]区间内的每个数x变为\(c^x\) 2.求[l,r]区间内数的和%p 首先,我们要了解一些数论 ...

  4. bzoj4869: [Shoi2017]相逢是问候(欧拉函数+线段树)

    这题是六省联考的...据说数据还出了点锅,心疼六省选手QAQ 首先要知道扩展欧拉定理... 可以发现每次区间操作都会使模数进行一次phi操作,而一个数最多取logp次phi就会变成1,这时后面的指数就 ...

  5. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛H题小Y与多米诺骨牌(线段树优化dp)

    题意 题目链接:https://www.nowcoder.com/acm/contest/91/H 来源:牛客网 题解 设l[i]l[i]l[i]为向左推第iii个骨牌最远能影响到的骨牌的编号,r[i ...

  6. CF 474E Pillars(线段树优化DP)

    CF 474E Pillars 题目描述 Marmot found a row with n n n pillars. The i i i -th pillar has the height of h ...

  7. hdu 4521(线段树优化dp)

    小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Pro ...

  8. AtCoder Regular Contest 085 F NRE 线段树优化dp

    题意 有长度为n初始全为0的数组A和仅由0和1组成的数组B.现在给出m个区间,每次可以选择某个区间[l,r],使得A数组下标在[l,r]之间的元素变为1.问A和B最小不同位置数量是多少. n,m< ...

  9. [BZOJ 4034][HAOI2015]树上操作(欧拉序列+线段树)

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

最新文章

  1. js、css分别实现元素水平垂直居中
  2. mysql2005备份_创建完整数据库备份 - SQL Server | Microsoft Docs
  3. 全球与中国数位屏市场前景展望与未来规划动向研究报告2022-2028年版
  4. 二叉树的遍历 (递归和非递归实现)
  5. 一键装机linux_(推荐)linux用一键安装包
  6. [树状数组][哈希]JZOJ 3240 Seat
  7. MTK 驱动---(11) EMI定制
  8. 发现一款好用的备份新浪博客的工具
  9. java 日志切面_自定义注解+面向切面整合的日志记录模块(一)
  10. 网络盘的计算机密码是什么,如何让win7映射网络驱动器记住密码
  11. 在html中生成动态表格数据,JavaScript实现网页动态生成表格
  12. 速率法和终点法的区别_两点法终点法速率法.doc
  13. sublime text3 主题-Boxy Theme
  14. [学习报告]《LeetCode零基础指南》第三讲循环-gyro
  15. 99乘法表,九九乘法表
  16. c语言case小于,大于和小于switch语句C
  17. html表单颜色背景图片大全,css背景颜色、背景图片,以及列表的多种样式
  18. SSL协议与数字证书原理
  19. 柠檬班软件测试靠谱吗 全程班毕业后7天就拿到了offer
  20. opencv手势识别(3_SVM算法识别)

热门文章

  1. MongoDB 学习笔记
  2. php 支付宝账单监控,支付宝账单监测 收款监测 实时监控
  3. 又来爬小说了,纯原创
  4. TYPE-C接口安卓手机直播快充领夹式无线麦克风方案
  5. Spartan6系列之时钟资源详解
  6. 老李玩微博经验分享之如何发微博
  7. SIMULIA 官方技术论坛全年时间表新鲜出炉!
  8. /proc 文件系统中的文件及内容介绍
  9. 编译原理算符分析器实现 -* c语言代码,C语言实现算符优先文法源代码(编译原理)...
  10. 杭州ALIENWARE外星人电脑(大悦城旗舰店),玩起来就是不一样