反素数应用 ZOJ 2562 More Divisors + Timus OJ 1748. The Most Complex Number

来源:互联网 发布:中国工业软件市场规模 编辑:程序博客网 时间:2024/05/18 02:52

More Divisors

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Everybody knows that we use decimal notation, i.e. the base of our notation is 10. Historians say that it is so because men have ten fingers. Maybe they are right. However, this is often not very convenient, ten has only four divisors -- 1, 2, 5 and 10. Thus, fractions like 1/3, 1/4 or 1/6 have inconvenient decimal representation. In this sense the notation with base 12, 24, or even 60 would be much more convenient.

The main reason for it is that the number of divisors of these numbers is much greater -- 6, 8 and 12 respectively. A good quiestion is: what is the number not exceeding n that has the greatest possible number of divisors? This is the question you have to answer.

Input:

The input consists of several test cases, each test case contains a integer n (1 <= n <= 1016).

Output:

For each test case, output positive integer number that does not exceed n and has the greatest possible number of divisors in a line. If there are several such numbers, output the smallest one.

Sample Input:
1020100
Sample Output:
61260


题意:给定一个数n,要求一个不超过n的数,并且因子数最多的最小的数。

思路:在之前我们先看一下反素数的概念。 http://blog.csdn.net/acdreamers/article/details/25049767

根据反素数的定义,会有如下两个性质。 反素数一定的因子一定是连续的质数,因为根据定义可以看出,如果x是反素数,那么他的因子数比任何一个小于它的数都要大,并且这个x是最小的。假设质数不是连续的,我们可以将最大的那个素数全部“填补”到断开那里,这样因子数不会变大,但是x确变小了。所以上述性质成立。 还有另外一个性质就是各个因子的指数是不升的。 可以用同样的方法证明。

有这些知识有什么用呢? 我们看看题目要求什么,就是不超过n的最大的反素数。是吧?怎么求呢?上面的链接里面说了搜索。 我们来看看是怎么搜的。 我们先得出一个足够长的素数表,由于是反素数,所以这需要这些素数连乘起来刚好超过题目给定的范围就行了。 然后我们开始枚举每个质因子的指数,在搜索的过程中不断的更新答案就行了。还有就是如果枚举因子指数的过程中,如果数字已经超过了n,就可以不用继续枚举了,因为后面枚举下去都是超过n的。到这里这道题目进本能解决了。


代码:

#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <string.h>using namespace std;#define LL unsigned long longint pri[]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ,31, 37, 41, 43, 47, 53 ,59 ,61, 67, 71, 73, 79, 83, 89, 97};LL n;LL cnt,ans;void dfs(int dep,LL num,LL x){    if(x>n) return;    if(num>cnt) { cnt=num; ans=x; }    else if(num==cnt) {        if(x<ans) ans=x;    }    for(LL i=1;i<63;++i) {        if(x>n/pri[dep]) break;        dfs(dep+1,num*(i+1),x*=pri[dep]);    }}int main(){    while(scanf("%lld",&n)==1) {        cnt=0,ans=n;        dfs(0,1,1);        cout<<ans<<endl;    }}


1748. The Most Complex Number

Time limit: 1.0 second
Memory limit: 64 MB
Let us define a complexity of an integer as the number of its divisors. Your task is to find the most complex integer in range from 1 to n. If there are many such integers, you should find the minimal one.

Input

The first line contains the number of testcases t (1 ≤ t ≤ 100). The i-th of the following t lines contains one integer ni (1 ≤ ni ≤ 1018).

Output

For each testcase output the answer on a separate line. The i-th line should contain the most complex integer in range from 1 to ni and its complexity, separated with space.

Sample

inputoutput
5110100100010000
1 16 460 12840 327560 64
Problem Author: Petr Lezhankin
Problem Source: Ufa SATU Contest. Petrozavodsk Summer Session, August 2009


跟上面那题一样。写法上我利用第二条性质我改进了一下。


代码:

#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <string.h>using namespace std;#define LL unsigned long longint pri[]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ,31, 37, 41, 43, 47, 53 ,59 ,61, 67, 71, 73, 79, 83, 89, 97};LL n;LL cnt,ans;void dfs(int dep,LL num,LL val,int tail){    if(num>cnt) { cnt=num; ans=val; }    else if(num==cnt&&ans>val) ans=val;    for(LL i=1;i<=tail;++i) {        if(val>n/pri[dep]) break;        dfs(dep+1,num*(i+1),val*=pri[dep],i);    }}int main(){    int _; cin>>_;    while(_--) {        cin>>n;        ans=n; cnt=0;        dfs(0,1,1,64);        cout<<ans<<" "<<cnt<<endl;    }}


0 0