Codeforces Round #948 (Div. 2) B (素数筛+思维)

题目链接: http://codeforces.com/contest/948/problem/B

2018-03-15 17:55:53

题意:小花和她的好朋友嘉瑜君玩游戏 第一个数字Xo确定 后面的数字X1由前面一个数字确定 确定的方式是 找到小于等于Xo的一个质数 在质数的倍数中 不小于Xo的最小的数字就是下一个数字  NODE:由上文可知 当Xo为质数的时候 Xo与X1可能相等  给出一个X2  要求求出最小的Xo

思路:先求出X1 刚开始的想法是这道题是否存在最优子结构 每一步都要求最小的话 是不是到Xo也就最小了 看过样例之后就会发现不是的  样例输入的是14  那么X1最小可以取8 比8小的质数取7  7的倍数中比8大的最小的就是14  X1等于8  那么Xo最小可以取7  比7小的质数取2  那么Xo最小也就是7了  但是这样是不对的 因为当X1不去最小取10时  Xo可以取到6  所以我的想法就是吧所有的X1的取值求出来 再把Xo所有的取值取出来 再求最小就好了 由题意可知 质数比第一个数字小 质数的倍数刚好大于是第二个数字  第二个数字刚好大于第一个数字 也就是连个数中间不存在质数的其他倍数 假设第二个数字是质数的x倍(x>=2)  那么第一个数字就是大于质数的x-1倍  小于等于x倍的数字 由此可以根据X2把所有的X1求出来 进而求出所有的X0

错因:因为写的不够优雅 所以超时了 因为符合要求的X1与X2之间差的就是一个质数大小的范围 所以只要找到能被X2整除的最大的那个质数就好了  同理Xo  超时的原因可能在于我每次都算一边 可以把这个初始化出来 每次直接调用

代码如下:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>

using namespace std;

#define Max 1000000

int n;
int prim[1000005];///为0的代表是素数 不为零的代表的是能整除的最大的素数是多少 时间复杂度接近nlogn

void Isprim()
{
    memset(prim , 0 , sizeof(prim));
    prim[1] = 1;///这个题中用不到1 设置一个不为0的数即可
    ///一个质数的不大于他本身的质数就是他自己
    for(int i=2; i<=1000000; i++)
    {
        if( prim[i]==0 )
        {
            for(int j=i*2; j<=1000000; j+=i)
            {
                prim[j] = i;
            }
        }
    }
}

void debug()
{
    for(int i=1; i<=100; i++)
    {
        printf("%d...
" , prim[i]);
    }
}

int main()
{
    Isprim();
//    debug();
    while( scanf("%d" , &n) != EOF )
    {
        int minn = 1e9;
        if( prim[n]==0 )
        {
            minn = n;
        }
        else
        {
            for(int i=n-prim[n]+1; i<=n; i++)//X1 可以是这些数字
            {
                if( prim[i]==0 )
                {
                    minn = min(minn , i);
                }
                else
                {
                    minn = min(minn , i-prim[i]+1);
                }
            }
        }
        printf("%d
" , minn);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/Flower-Z/p/8575140.html