zoukankan      html  css  js  c++  java
  • ACM-Antiprime数

     

    问题描述: swust打不开,随便找了个博客。。。。

    对于任何正整数x,起约数的个数记做g(x).例如g(1)=1,g(6)=4.

    定义:如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数.

    现在给一个N,求出不超过N的最大的反素数.

    比如:输入1000 输出 840

    思维过程:

    求[1..N]中最大的反素数-->求约数最多的数(约数同样多取数值小的)

    简单证明:

    如果X是答案,但X不是约数最多的数,假设约数最多的数是Y,那么Y>X,否则不符合反质数的定义。

    那么很明显Y也是一个反质数,且Y比X大,那么答案应该是Y而不是X。

    如果求约数的个数 756=2^2*3^3*7^1

    (2+1)*(3+1)*(1+1)=24

    基于上述结论,给出算法:按照质因数大小递增顺序搜索每一个质因子,枚举每一个质因子

    为了剪枝:

    性质一:一个反素数的质因子必然是从2开始连续的质数.

    因为最多只需要10个素数构造:2,3,5,7,11,13,17,19,23,29

    性质二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....

     1 //// Antiprime数.cpp : 定义控制台应用程序的入口点。
     2 ////
     3 //
     4 #include "stdafx.h"
     5 
     6 #include<cstdio>
     7 #include<iostream>
     8 using namespace std;
     9 typedef long long ll;
    10 int prime[12] = { 0, 2, 3, 5, 7, 11, 13, 17, 19, 21, 23 };
    11 //相应的限制次数{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    12 //2*3*5*7*11*13*17*19*21*23>n,所以只需考虑到23即可
    13 ll n, BestSum, BestNum;
    14 
    15 //num表示当前数字大小、sum表示当前数字的约数个数、limit表示第k个素数的上限,k表示第k个素数
    16 void solve(ll num, ll sum, ll limit, ll k)
    17 {
    18     //cout << "=======================:      pos:" << k << "	div:" << sum << "	num:" << num << "	limit:" << limit << endl;
    19     if (sum>BestSum){
    20         BestSum = sum;
    21         BestNum = num;
    22     }
    23     else if (sum == BestSum&&num<BestNum){//约数个数一样时,取小数
    24         BestNum = num;
    25     }
    26     for (int i = 1; i <= limit; i++){//素数k取i个
    27         cout << "=====================================================================" << endl;
    28         cout << "now num:" << num << "	k:" << k << "	i:" << i << "	limit:" << limit << endl;
    29         cout << num << "*prime[" << k << "]=" << "="<<num <<"*"<<prime[k]<< "=" << num * prime[k] << endl;
    30         cout << "sum:" << sum << "	i:" << i << "	sum*(1+" << i << ")=" << sum*(1 + i) << endl;
    31         cout << "=====================================================================" << endl<<endl;
    32         num *= prime[k];
    33         if (num>n) return;
    34             solve(num, sum*(1 + i), i, k + 1);
    35     }
    36 }
    37 int main(){
    38     cin >> n;
    39     solve(1, 1, 10, 1);//每个数最多被分解成10质数的乘积
    40     cout << BestNum;
    41     return 0;
    42 }

     下面是当n=20时,问题解的遍历图形。

  • 相关阅读:
    JavaScript中字符串处理的一些函数
    JavaScript中的call、apply、bind方法的区别
    JavaScript中的数组与伪数组的区别
    关于字符集和字符编码那些事
    JavaScript的技巧和最佳实践
    Linux下编辑利器vim,vimrc,viminfo的高级用法
    pdo,更高的sql安全性
    Centos下cacti的安装
    nginx中的502错误
    mac下webpagetest搭建
  • 原文地址:https://www.cnblogs.com/x739400043/p/8598906.html
Copyright © 2011-2022 走看看