首页 > 其他分享 >【51Nod1386】双马尾机器人(分块+dp)

【51Nod1386】双马尾机器人(分块+dp)

时间:2022-10-28 18:34:25浏览次数:64  
标签:小于 sta 分块 质数 sqrt 因子 dp 51Nod1386

对于这种找互质的数的集合的题,一般是讨论每个数的质因子会不会有重复。

听说这种互质的题把质因子分为小于 \(\sqrt{n}\) 和大于 \(\sqrt{n}\) 是经典套路?

因为当 \(n\) 很小的时候,小于 \(\sqrt{n}\) 的质数并不多。比如对于这一题,小于 \(\sqrt{N=1000}\) 的数只有 \(11\) 个。

那么对于那些只有小于 \(\sqrt{N}\) 的质因子的数进行状压 dp,设 \(dp(i,j)\) 为前 \(i\) 个数中,所有选出的数的所有质因子的状态为 \(j\)(只考虑小于 \(\sqrt N\) 的质因子)。

\(j\) 的定义:如果选出的数的所有质因子中出现了第 \(k\) 个质数,那么把 \(j\) 在二进制下的第 \(k\) 位设为 \(1\),否则为 \(0\)。

例如,如果出现了 \(2\)(第 \(1\) 个质数)、\(5\)(第 \(3\) 个质数)和 \(7\)(第 \(4\) 个质数的话),\(j\) 就应该是 \((1101)_2\)。

那么假设 \(dp(i-1)\) 都已经计算完毕,现在要计算 \(dp(i,j|sta[i])\),其中 \(j\) 是某个状态,\(sta[i]\) 是 \(i\) 的质因子状态。那么现在考虑的是状态 \(j|sta[i]\)。

  1. \(dp(i,j|sta[i])=dp(i-1,j|sta[i])\)。意思就是前 \(i-1\) 个数中已经选出了状态 \(j|sta[i]\),那么数 \(i\) 肯定不能在加入这个方案内(不然不互质),所以选的数不增不减。

  2. \(dp(i,j|sta[i])=dp(i-1,j+1-(maxp_i>11))\)。意思就是前 \(i-1\) 个数中已经选出了状态 \(j\),那么现在肯定可以加入数 \(i\)。但是由于我们这里只考虑加入质因子都小于 \(\sqrt{N}\) 的情况,所以要减去一个 \(maxp_i>11\)。

现在对只有小于 \(\sqrt{N}\) 的质因子的数都处理完了,那么对于含有大于 \(\sqrt{N}\) 的质因子的数怎么处理呢?(不妨设所有大于 \(\sqrt{N}\) 小于 \(N\) 的质数有 \(m\) 个)

不难发现,这些数恰好仅含有一个大于 \(\sqrt{N}\) 的质因子。所以我们至少要选 \(m\) 个数才能保证是“极大方案”。又因为要保证选的数最少,所以要恰好选 \(m\) 个就行了。

最后可以把 \(1\) 也取上。

代码:

#include<bits/stdc++.h>

#define N 1010
#define INF 0x7fffffff

using namespace std;

int t,n,k;
int cnt,prime[N],maxp[N],sta[N];
int dp[2][1<<12];
bool notprime[N];

void init()
{
	for(int i=2;i<=1000;i++)
	{
		if(!notprime[i])
		{
			prime[++cnt]=i;
			maxp[i]=cnt;
			sta[i]=(cnt<=11?(1<<(cnt-1)):0);
		}
		for(int j=1;j<=cnt&&i*prime[j]<=1000;j++)
		{
			int v=i*prime[j];
			notprime[v]=true;
			maxp[v]=max(maxp[i],j);
			sta[v]=sta[i]|(j<=11?(1<<(j-1)):0);
		}
	}
}

int main()
{
	init();
	scanf("%d",&t);
	for(int T=1;T<=t;T++)
	{
		scanf("%d%d",&n,&k);
		int m=1;
		while(prime[m]<=n) m++;
		m--;
		int tmp=max(0,m-11);
		m=min(m,11);
		int mpow=(1<<m);
		for(int i=0;i<mpow;i++) dp[0][i]=INF;
		dp[0][0]=0;
		int now=1;
		for(int i=1;i<=n;i++,now^=1)
		{
			for(int j=0;j<mpow;j++) dp[now][j]=dp[now^1][j];
			if(i==k) continue;
			for(int j=0;j<mpow;j++)
				if(!(j&sta[i])&&dp[now^1][j]!=INF)
					dp[now][j|sta[i]]=min(dp[now^1][j|sta[i]],dp[now^1][j]+1-(maxp[i]>11));
		}
		printf("Case #%d: %d\n",T,dp[now^1][mpow-1]+tmp+(k!=1));
	}
	return 0;
}

标签:小于,sta,分块,质数,sqrt,因子,dp,51Nod1386
From: https://www.cnblogs.com/ez-lcw/p/16837046.html

相关文章

  • [USACO20OPEN]Sprinklers 2_ Return of the Alfalfa(dp)
    先讲一下等会要用到的定义:红格代表被甜玉米洒水器喷洒到的方格,蓝格代表被苜蓿洒水器喷洒到的方格。橙格代表有甜玉米洒水器的方格,紫格代表有苜蓿洒水器。\((a,b)\)......
  • [NOI Online 2020 #2 提高 B] 子序列问题 (dp+线段树)
    真的是事后诸葛亮,一下考场就知道怎么做了,现在把题解补回来看到这个问题,我第一下想到的就是\(dp\)。如何\(dp\)?设\(dp[i]\)为以\(i\)为右端点的所有子串的答案之和......
  • NOIP 前 CF*2300 左右 dp 做题记录
    iFTL独立做出形象理解为两个横放的羽毛球盒,第一个放长t1的,第二个放长t2的,然后手推可得一次共同发射之后必是平平的盒子底部,仿佛回到了最初,至此可发现子结构。基于此......
  • 求大神解答:利用python爬取各县GDP结果为空,求大神看看我的代码问题在哪?
    目标url=红黑人口库代码importrequestsfromlxmlimportetreeimporttimeif__name__=='__main__':  url='https://pagead2.googlesyndication.com/getconfig/soda......
  • API项目附加cshtml(报错Cannot find the fallback endpoint specified by route value
    举例elsa-core项目添加_Host.cshtml。在项目中直接按照Elsa的要求添加Pages文件后,运行项目正常环境正常。由于项目是api项目发布后添加的Pages文件并不属于Views中,所以添......
  • 「REMAKE系列」概率期望dp篇
    常见模型技巧总结概率正推,期望倒推简单概率期望简单分类讨论。P1297[国家集训队]单选错位根据题目推导。UVA11021Tribles需要一些小观察的题目01最终位置确定,倒......
  • 洛谷 P1077 [NOIP2012 普及组] 摆花 (DP)
    https://www.luogu.com.cn/problem/P1077题目描述摆上m盆花。一共有n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同......
  • CF1163D Mysterious Code ACA+DP
    将两个串插入AC自动机,AC自动机带点权,S串带权值1,T串带权值-1,对树在构建时求树上点权前缀和,然后设表示到的第个字符,在ACA上的第个节点时的答案,那么就有转移方程:#include<bits......
  • 【PNR#2 Div1 D】找零(DP)(贪心)
    找零题目链接:PNR#2Div1D题目大意有500,100,50,10,5,1这些面额的纸币,你有X块钱,使用最少的纸币数表示的。然后有一些物品,每种只有一个,有费用。每次你可以选择一些......
  • AcWing1069.凸多边形的划分(区间DP)
    SLOJP2067.三角剖分问题AcWing1069.凸多边形的划分(区间DP)题目描述给定由N顶点组成的凸多边形每个顶点具有权值将凸N边形剖分成N-2个三角形求N-2个三角形......