sgu116

本文解析了SGU116题目——超级素数目录问题,介绍了如何通过改进欧拉筛法来生成超级素数序列,并利用动态规划解决求解指定整数的超级素数目录及构成序列。

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



SGU116 Index of super-prime

题目大意:

序列P1, P2, … ,Pk, …为超级素数序列。超级素数是指一个数在本身是素数的基础上,他在素数序列里的下标也是素数。例如3就是超级素数,但7不是。如果一个数不能由一个或多个超级素数相加而得,那么这个数的超级素数目录是0。但是如果存在这样的序列,那么这个数的超级素数目录就是这个序列的最小长度。你的任务是照出这个数的超级素数目录,以及这个序列。

输入:

一个正整数N(0<N<=10000)

输出:

输出超级素数目录,并且如果序列存在的话,在另一行按不上升的顺序输出该序列。

样例输入:

6

样例输出:

2

3 3


这道题还是很基础的。

一个素数一定大于他在素数序列里的下标(这是常识!)

首先我们要求出超级素数,这个只需在欧拉筛里做个小小的改进。


下一步就是用这个序列数字N。

最基础的背包DP...

设f[i]————数字i的超级素数目录。

  转移方程:f[i]=MIN(f[i-super_prime[j]]+1)(super_prime[]为超级素数序列);

  设pre[i]等于对应的超级素数super_prime[j];

  输出的时候倒着输出即可。


注意事项:

1.输出顺序(仔细看题!),如果错了的话你会WA在Test8(所以前面七个点心态在哪?)

2.超级素数在列举的时候倒序列举(这样可以优先使用大素数)


下面附上我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
int n;
bool check[10030];
int super_prime[10030],prime[10030],super_total,total;
int f[10030],pre[10030],print[10030],t;
void super_eular() //超级欧拉筛
{
  int i,j;
  check[0]=check[1]=false;
  for (i=2;i<=n;i++)
    {
    if (check[i])
      {
	  prime[++total]=i;
	  if (check[total])
	    super_prime[++super_total]=i; //记录超级素数序列
	  }
	for (j=1;j<=total;j++)
	  {
	  if (i*prime[j]>n)
	    break;
	  check[i*prime[j]]=false;
	  if (i%prime[j]==0)
	    break;
	  }
	}
  return ;
}
void dp() //背包
{
  int i,j;
  for (i=1;i<=n;i++)
    for (j=super_total;j>=1;j--)
      if (i-super_prime[j]>=0)
        if (f[i-super_prime[j]]+1<f[i])
          {
          f[i]=f[i-super_prime[j]]+1;
          pre[i]=super_prime[j];
  	      }
  return ;
}
void init()
{
  int i;
  memset(check,true,sizeof(check));
  scanf("%d",&n);
  for (i=1;i<=n;i++)
    f[i]=1000000000;
  super_eular();
  dp();
  if (f[n]!=1000000000)
    {
    printf("%d\n%d",f[n],pre[n]);
    for (i=n-pre[n];i;i=i-pre[i])
      printf(" %d",pre[i]); //输出序列
    printf("\n");
    }
  else
    printf("0");
  return ;
}
int main()
{
  init();
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值