hdu4542 小明系列故事——未知剩余系(反素数打表待改!!不会!!)

本文提供了一道来自HDU在线评测系统的题目4542的解答思路及代码实现。该题涉及求解特定条件下最小的反素数问题,采用递归深度优先搜索结合贪心算法,并通过预处理表格进行优化。

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


http://acm.hdu.edu.cn/showproblem.php?pid=4542


这道题时间卡的也太紧了换着打了几种表都不行,看了下别人的表打的都莫名其妙,里面的剪枝也被弄懂,直接绕晕了。。用别人的代码改了改,改天在看这题。。


#include <stdio.h>
#include <algorithm>
#include <string.h>

using namespace std;

typedef long long ll;
const int N = 50005;//互质数的个数不超过k最大值
const ll INF = (((ll)1)<<62)+1;

int p[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};

ll ans, n;//ans表示满足约数为n的反素数,通过多次贪心求的最小值
int num[N];//f[N]代表非约数个数为n的最小x

void table()
{
  /*  num[1] = num[2] = 0;
    for(int i = 3; i <= N; i++)
    {
        num[i] = i;
        for(int j = 1; j <= (i/2+1); j++)
        {
            if(i%j == 0) num[i]--;
        }
        num[i]--;
    }
    memset(f, 0, sizeof(f));
    for(int i = 1; i <= N; i++)
    {
        if(f[num[i]] == 0) f[num[i]] = i;
    }*/
    for(int i=1;i<N;i++) num[i] = i;
    for(int i=1;i<N;i++)
    {
        for(int j=i;j<N;j+=i) num[j]--;
        if(!num[num[i]]) num[num[i]] = i;
        num[i] = 0;
    }
}

void dfs(ll step, ll cur, ll cnt, ll Maxnum)//cur表示当前因子个数所对应的反素数,cnt表示当前因子个数
{
    if(cnt > n) return;
    if(cnt==n && cur<ans) ans = cur;//更新最小反素数
    ll tmp = cur;//在原先反素数的基础上乘第step个素数
    for(int i = 1; i <= Maxnum; i++)//枚举第step个素数的个数
    {
        if(ans / p[step] < tmp || cnt*(i+1) > n) break;
        tmp *= p[step];
       /* tmp*=p[step];
        if(tmp>ans || (cnt*(i+1))>n) break;//若乘上这个质因子超过了已知最大反素数,不满足求最小反素数的条件,返回*/
        if(n%(cnt*(i+1))==0)
            dfs(step+1, tmp, cnt*(i+1), i);//下一个质因子肯定个数要比这个少,因子个数累乘
    }
}

int main()
{
  //  freopen("in.txt", "r", stdin);
    int t, type, Case = 1;
    table();
  /*  for(int i = 1; i <= 20; i++)
    {
        printf("%d %lld\n", i, num[i]);
    }*/
    scanf("%d", &t);
    while(t--)
    {
      //  ans = 0;
        scanf("%d%lld", &type, &n);
        if(type == 1)
        {
            ans = num[n];
        }
        else if(type == 0)
        {
            ans = INF;
            dfs(0, 1, 1, 62);
        }
        printf("Case %d: ", Case++);
        if(ans == 0) printf("Illegal\n");
        else if(ans >= INF) printf("INF\n");
        else printf("%lld\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值