1. 程式人生 > >洛谷 P1463、POI2002、HAOI2007 反素數

洛谷 P1463、POI2002、HAOI2007 反素數

最大 ext 離開 out nbsp 搜索剪枝 cor 理由 void

想打表的自行離開

題目描述

對於任何正整數x,其約數的個數記作g(x)。例如g(1)=1、g(6)=4。

如果某個正整數x滿足:g(x)>g(i) 0<i<x,則稱x為反質數。例如,整數1,2,4,6等都是反質數。

現在給定一個數N,你能求出不超過N的最大的反質數麽?

不能

題意:

求最小的x∈[1,N],使得x為 g(x)最大的數 中最小的一個。

1.x不會有超過10個不同質因子。理由:2*3*5...*31>2*1e9,2*3*5...*29<2*1e9。2~29質數剛好10個。

2.質因子指數不會大於30。理由:當取最小的質因子2時,231>2*1e9,230

<2*1e9。

3.若x=p1^c1*p2^c2...pn^cn,則x的因子個數為(c1+1)(c2+1)...(cn+1)。即:g(x)=(c1+1)(c2+1)...(cn+1)。

4.質因子連續、指數不升。理由:反證法。若x=p1^c1*p2^c2...pn^cn,且存在pn-1<p<pn,則x0=p1^c1*p2^c2...pn-1^cn-1*p^cn<x,g(x0)=g(x),不符合題意。

                   若存在cn>cn-1,則將cn,cn-1位置交換,也不符合題意

綜上所述,可以用上述幾個約束條件進行搜索剪枝。

代碼就是簡單的DFS。

#include<iostream>
#include<vector>
typedef long long ll;
using namespace std;
const ll pa[16]={0,2,3,5,7,11,13,17,19,23,29};
ll n,ans=1,g=0;

void dfs(ll p,ll t,ll now,ll ng)
{
    if(now>n) return;
    if(p>10) return;
    ll temp=ng;
    for(ll i=1;i<=t;i++){
        now*=pa[p];
        ng
=temp*(i+1); if(now>n) return; if(ng>g) ans=now,g=ng; if(ng==g) ans=min(now,ans); dfs(p+1,i,now,ng); } } signed main() { cin>>n; dfs(1,30,1,1); cout<<ans; return 0; }

洛谷 P1463、POI2002、HAOI2007 反素數