4524: [Cqoi2016]伪光滑数

本文详细解析了[Cqoi2016]伪光滑数问题,介绍了如何通过筛选2到128之间的所有质数并对其进行编号来解决此问题。文章进一步阐述了使用可持久化可并堆+DP的方法来求解特定条件下第E大的N-伪光滑数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4524: [Cqoi2016]伪光滑数

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 280   Solved: 133
[ Submit][ Status][ Discuss]

Description

若一个大于R的整数J的质因数分解有F项,其最大的质因子为ak,并且满足ak^k≤N,
ak<128,我们就称整数J为N-伪光滑数。
现在给出L,求所有整数中,第E大的N-伪光滑数。

Input

只有一行,为用空格隔开的整数L和E。
2 ≤ N ≤ 10^18, 1 ≤ K ≤ 800000,保证至少有 E 个满足要求的数

Output

只有一行,为一个整数,表示答案。

Sample Input

12345 20

Sample Output

9167

HINT


Source

[ Submit][ Status][ Discuss]




正解是可持久化可并堆 + dp,,看了题解才会= =

先筛出2~128内所有质数,分别给它们一个编号

定义f[i][j]:质因数最大为pri[i],由j个质因数组成的数的集合

定义g[i][j]:质因数最大为pri[1] ~ pri[i],由j个质数组成的数的集合

定义U*g为集合U中所有数字乘以g,定义A + B为集合A,B取并集

那么很好写出f,g的方程,f[i][j] = ∑g[i-1][k]*pri[i]^(j-k),g[i][j] = g[i-1][j] + f[i][j]

询问的话先把所有f[i][j]中最大的数都扔进堆里,每次取出最大的数字,把它所在集合的次大数扔进堆

不断重复K次就是答案了

f,g的集合可以用可持久化可并堆 + 懒惰标记解决

这样就能保证存数集最大数的那个堆里的元素大小线性,因为每次取出一个数新放两个数

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<bitset>
using namespace std;

typedef long long LL;
typedef double DB;
const int maxn = 8E5 + 80;
const int T = 15;

struct Heap{
	int L,ch[2]; LL val,Mark;
}h[maxn*T];

struct Node{
	LL val; int num; Node(){}
	Node(int num,LL val): num(num),val(val){}
	bool operator < (const Node &B) const {return val < B.val;}
};

LL N,mi[100][100],pri[100];
int K,tot,cnt,f[100][100],g[100][100];
bool not_pri[200];

priority_queue <Node,vector<Node>,less<Node> > Q;

void Pre_Work()
{
	for (int i = 2; i < 128; i++)
	{
		if (!not_pri[i]) pri[++tot] = i;
		for (int j = 1; j <= tot; j++)
		{
			int Nex = i*pri[j];
			if (Nex >= 128) break;
			not_pri[Nex] = 1;
			if (i % pri[j] == 0) break;
		}
	}
	for (int i = 1; i <= tot; i++)
	{
		mi[i][0] = 1;
		for (int j = 1; j <= 64; j++)
		{
			if ((DB)(pri[i]) > (DB)(N) / (DB)(mi[i][j-1])) break;
			mi[i][j] = mi[i][j-1]*pri[i];
		}
	}
}

void pushdown(int x)
{
	if (h[x].Mark == 1) return;
	h[x].val *= h[x].Mark;
	for (int i = 0; i < 2; i++)
		if (h[x].ch[i])
		{
			h[++cnt] = h[h[x].ch[i]];
			h[cnt].Mark *= h[x].Mark; h[x].ch[i] = cnt;
		}
	h[x].Mark = 1;
}

int Merge(int x,int y)
{
	if (!x) return y; if (!y) return x;
	pushdown(x); pushdown(y);
	if (h[x].val < h[y].val) swap(x,y);
	int ret = ++cnt; h[ret] = h[x];
	h[ret].ch[1] = Merge(h[ret].ch[1],y);
	if (h[h[ret].ch[1]].L > h[h[ret].ch[0]].L) 
		swap(h[ret].ch[0],h[ret].ch[1]);
	h[ret].L = h[h[ret].ch[1]].L + 1; return ret;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> N >> K; Pre_Work();
	f[0][0] = g[0][0] = ++cnt; h[cnt].Mark = h[cnt].val = 1;
	for (int i = 1; i <= tot; i++)
		for (int j = 0; j <= 64; j++)
		{
			if (!mi[i][j]) {g[i][j] = g[i-1][j]; continue;}
			for (int k = 0; k < j; k++) if (g[i-1][k])
			{
				LL now = h[g[i-1][k]].val*h[g[i-1][k]].Mark;
				h[++cnt] = h[g[i-1][k]]; h[cnt].Mark *= mi[i][j-k];
				f[i][j] = Merge(f[i][j],cnt);
			}
			g[i][j] = Merge(g[i-1][j],f[i][j]);
			if (!f[i][j]) continue;
			pushdown(f[i][j]); Q.push(Node(f[i][j],h[f[i][j]].val));
		}
	for (int I = 1; ; I++)
	{
		Node k = Q.top(); Q.pop(); int now = k.num;
		if (I == K) {cout << k.val; break;}
		for (int i = 0; i < 2; i++)
			if (h[now].ch[i])
			{
				int Nex = h[now].ch[i]; pushdown(Nex);
				Q.push(Node(Nex,h[Nex].val));
			}
	}
	return 0;
}

### 130电机PID控制参数调整方法 对于130电机而言,在应用PID控制器时,其参数调整需考虑具体应用场景下的动态特性。通常情况下: - **比例系数 (Kp)** 加快系统响应速度并提升调节精度[^1]。在130电机控制系统中,适当增大Kp可以使电机更快达到目标位置或转速,但如果设置过大,则可能导致超调量增加甚至引起振荡。 - **积分系数 (Ki)** 主要作用在于消除静态偏差,即当存在持续性的误差时通过累积效应逐渐减小直至完全清除这种长期存在的差异。针对130电机来说,合理配置Ki有助于确保长时间运行后的精准度不会因外部干扰而偏离预期轨迹。 - **微分系数 (Kd)** 对改善系统的瞬态行为有帮助,特别是抑制快速变化引起的波动,从而优化整体稳定性表现。就130电机的应用场景来看,合适的Kd可以有效减少启动瞬间或者负载突变时刻可能出现的剧烈抖动现象。 值得注意的是,实际操作过程中往往需要依据具体的工况条件反复试验来找到最适宜的一组PID参数组合。这可能涉及到逐步逼近法、Ziegler-Nichols法则等多种经典调试策略的选择与运用。 ```python # Python模拟简单的PID计算过程 class PIDController: def __init__(self, kp=1.0, ki=0.0, kd=0.0): self.kp = kp self.ki = ki self.kd = kd self.previous_error = 0 self.integral = 0 def compute(self, setpoint, measured_value): error = setpoint - measured_value derivative = error - self.previous_error self.integral += error output = (self.kp * error + self.ki * self.integral + self.kd * derivative) self.previous_error = error return output ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值