牛客练习赛14

时间:2023-02-13 20:17:44

链接:https://www.nowcoder.com/acm/contest/82/D

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

     点点是一名出色的狼人。众所周知,狼人只有在满月之夜才会变成狼。

    同时,月亮的大小随着时间变化,它的大小变化30天为一循环。它的变化情况(从第一天开始)为0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 然后又再一次循环。

    今年夏天点点很无聊,于是开始看月亮。由于点点很忙,所以他只选择一段连续的时间看月亮,并把月亮的大小记录了下来。

    现在,他告诉你他记录下东西,让你告诉他下一天(即点点记录下的最后一天的第二天)的月亮是比前一天(即点点记录下的最后一天)大还是小。

输入描述:

给你一个正整数n表示点点记录下的时间个数。
下一行n个自然数表示点点记录下的月亮大小。

输出描述:

一个字符串。
如果下一天的比前一天的大则输出"UP"
如果下一天的比前一天的小则输出"DOWN"
如果无法判断则输出"-1"
示例1

输入

5
3 4 5 6 7

输出

UP
示例2

输入

8
12 13 14 15 14 13 12 11

输出

DOWN
示例3

输入

1
8

输出

-1

备注:

n≤100 0 ≤ a i ≤ 15
保证输入的数据满足月亮变化的循环规律
【分析】:注意单个数字边界0、15是要特判的,他们之后的升降确定了的!
【代码】:
#include<bits/stdc++.h>

using namespace std;

#define N 505
#define inf 99999999
int a[5000];
int main()
{
    int n;
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    if(n==1&&a[1]!=15&&a[1]!=0)
    {
        return 0*printf("-1\n");
    }
    if(n==1&&a[1]==15) return 0*puts("DOWN");
    if(n==1&&a[1]==0) return 0*puts("UP");
    if(a[n-1]<a[n])
    {
        if(a[n]==15) printf("DOWN\n");
        else printf("UP\n");
    }
    if(a[n-1]>a[n])
    {
        if(a[n]==0) printf("UP\n");
        else printf("DOWN\n");
    }
    return 0;
}

  

链接:https://www.nowcoder.com/acm/contest/82/A
来源:牛客网

题目描述

t次询问,每次给你一个数n,求在[1,n]内约数个数最多的数的约数个数

输入描述:

第一行一个正整数t
之后t行,每行一个正整数n

输出描述:

输出t行,每行一个整数,表示答案
示例1

输入

5
13
9
1
13
16

输出

6
4
1
6
6

备注:

对于100%的数据,t <= 500 , 1 <= n <= 1000000000000000000
【分析】:

(1)此题最容易想到的是穷举,但是肯定超时。

(2)我们可以知道,计算约数的个数和质因数分解有着很大的联系:

若Q的质因数分解为:Q=p1^k1*p2^k2*…*pm^km(p1…pm为素数,k1…km≥1),则Q有(k1+1)(k2+1)…(km+1)个约数。

但是质因数分解的时间复杂度很高,所以也会超时。

(3)通过以上的公式,我们可以“突发奇想”:为何不能把质因数分解的过程反过来呢?

这个算法就是枚举每一个素数。初始时让m=1,然后从最小的素数2开始枚举,枚举因子中包含0个2、1个2、2个2…k个2,直至m*2^k大于区间的上限N。在这个基础上枚举3、5、7……的情况,算出现在已经得到的m的约数个数,同时与原有的记录进行比较和替换。直至所有的情况都被判定过了。

这个算法的优化:如果p1*p2*p3*……*pk>N(pi表示第i个素数),那么只要枚举到p k-1,既不浪费时间,也不会遗漏。

根据以上的算法,对于上限需要枚举436555171个数,也会超时,不过可以过70-80%的数据。

(4)以上的算法还不是最好的,还可以继续优化。

我们看以下的例子:

6=2*3 10=2*5

6和10的质因数分解“模式”完全相同,所以它们的约数个数是相同的。但是由于3<5,所以6<10。

12=2^2*3 18=3^2*2

12和18的质因数分解“模式”完全相同,所以它们的约数个数是相同的。但是由于12的质因数分解中2的指数大于3的指数,18的质因数分解中3的指数大于2的指数,所以12<18。

根据以上的举例,我们也可以对(3)中的算法进行一个改进:可以在枚举时进行一个优化,使得枚举到的数字中2的指数不小于3的指数,3的指数不小于5的指数……这样我们就能够得到质因数分解“模式”相同的最小数(证明略)。再对于每一个得到的数进行比较和记录。这个算法对于上限只需要枚举34136个数,几乎达到了极限。

【代码】:

#include<stdio.h>
#define inf 9999999
int p[20] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};

long long  max,n;
long long num;
void get(long long m,int f,int t,int pr)//m代表当前值,f当前的素数,t约数的个数,pr指数限制
{

    if(t>max||t==max)
    {
        max=t;
    }
    int j=0,l=1,nt;
    long long i=m;
    while(j<pr)
    {
        j++;
        l++;
        if(n/i<p[f]) break;
        nt=t*l;  //约数的个数
        i=i*p[f];
        if(i<=n)
            get(i,f+1,nt,j);//为什么是 j,为了是 前一个素数的指数大于后一个素数的指数
    }
}
int main()
{
    int t;
    scanf("%d",&t);;
    while(t--)
    {
        max=-1;
        scanf("%lld",&n);
        get(1,1,1,30);
        printf("%lld\n",max);
    }
}