Topcoder SRM 661 (Div.1) 250 MissingLCM - 数论

【题意】

给你一个数N(1<=N<=10^6),要求最小的M(M>N),使得lcm(n+1,n+2,...m)=lcm(1,2,3,...,m)

【思路】

手速太慢啦,等敲完代码的时候发现比赛已经结束了

一开始我想直接枚举m,并判断lcm(1,..,m)与lcm(n+1,n+2,...,m)是否相等,但发现,当求到lcm(1,...,40)的时候就爆LL了

显然不能这样求

也就是说,要求出具体lcm(1,2,...,m)的值是很困难的

怎么求

可以把它分解质因数,分解成几个质数相乘的形式

判断lcm(1,...,m)和lcm(n+1,n+2,...,m)的质因数是否完全一样。

但是仅仅1~1000000的质数有8万个

枚举m再枚举质数显然吃不消。

然而我注意到有一条性质(不知道算不算)

假设有质数K,可以求出t,使得K的t次方刚好小于m(K^t<=m)

那么lcm(1,2,...,m)分解质因数中一定而且最多有t个质数K连乘,

这样就可以很快地吧lcm(1,2,...,m)分解质因数

那么怎么把lcm(n+1,n+2,...,m)分解质因数呢

仍然假设质数K,可以求出最大的t,以及一个常数c(1<=c<K),使得 n+1<=c*K^t<=m
那么lcm(n+1,n+2,...,m)分解质因数中一定而且最多有t个质数K连乘。

比如说质数3,n=16,m=22,可以求的c=2,t=2,即17<=2*3^2=18<=22,这样lcm(17,18,19,20,21,22)中最多有2个质数3连乘

既然知道怎么求lcm(n+1,n+2,..,m)和lcm(1,2,..,m)了

来探讨一下怎么求最小的m吧

我们想让这两个lcm分解质因数后完全一样,也就是说连乘的质数个数也完全相等。

也就是说,对于每个质数K都可以满足,存在c和最大的t 使得n+1<=c*K^t<=m

对于大于n小于m的质数,我们假设是P,那么一定n+1<=P<=m,一定可以满足条件

所以我们就只看小于等于n的质数就可以了

因为要使每个小于N的质数K,都存在c和最大的t 使得n+1<=c*K^t<=m,

我们枚举每一个质数,并求得c和t,使得刚好c*K^t>=n

答案就是 max( c*K^t )

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 1005
#define MAXM 40005
#define INF 0x3fffffff
using namespace std;
typedef long long LL;
LL i,j,k,n,m,x,y,T,big,cas,num;
bool flag;

LL cur,ans;

bool prim[2000005];
LL ver[2000005];
void GetPrim(LL size)
{
    LL m=sqrt(size+0.5);
    memset(prim,0,sizeof(prim));//可以根据情况进行清空操作
    num=0;//把找到的质数存入ver数组中,num为ver数组的长度 

    //如果要获得质数数组,i就枚举到size,如果仅仅是prim数组,就枚举到m
    for (LL i=2;i<=size;i++)
    {
        if (!prim[i])
        {
            ver[++num]=i;
            if (i<=m) for (LL j=i*i;j<=size;j+=i) prim[j]=1;
        }
    }
}

class MissingLCM
{
        public:
        int getMin(int N)
        {
            LL n=N;
            GetPrim(n);
            LL ans=n+1;
            for (i=num;i>=1;i--)
            {
                LL u=ver[i];
                for (j=1;j*u<=n;j*=u);

                ans=max(ans,(n/j+1)*j);
            }
            return ans;
        }
};
时间: 2024-10-10 21:10:28

Topcoder SRM 661 (Div.1) 250 MissingLCM - 数论的相关文章

TopCoder SRM 596 DIV 1 250

body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } Problem Statement      You have an array with N elements. Initially, each element is 0. You can perform the following operations: Increment operation:

Topcoder SRM 687 (Div 2) 250.Quorum

Problem Statement   In one organization they have n different committees. The organization has a very large number of employees. Each employee is a member of each committee. Each committee has a quorum: the smallest number of members that have to be

TopCoder SRM 634 Div.2[ABC]

TopCoder SRM 634 Div.2[ABC] ACM 题目地址: TopCoder SRM 634 赛后做的,感觉现场肯定做不出来Orz,简直不能多说. Level One-MountainRanges[水题] 题意: 问序列中有几个完全大于旁边的峰. 分析: 傻逼题,不多说. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: one.cpp * Create Date: 2014-09-26 21:01:23 * Desc

TopCoder SRM 628 DIV 2

250-point problem Problem Statement    Janusz is learning how to play chess. He is using the standard chessboard with 8 rows and 8 columns. Both the rows and the columns are numbered 0 through 7. Thus, we can describe each cell using its two coordina

TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization &amp; Codeforces 839 E

传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相加,含有n个不同变量的式子的最大值. 另外限制了每一个变量的最大最小值R[i]和L[i]和所有变量之和的最大值Max. n<=13 题外话: 刚开始做这道题的时候,感觉意外眼熟? codeforces 839 E(此题的退化版):http://codeforces.com/contest/839/pro

竞赛图的得分序列 (SRM 717 div 1 250)

SRM 717 DIV 1 中 出了这样一道题: 竞赛图就是把一个无向完全图的边定向后得到的有向图,得分序列就是每个点的出度构成的序列. 给出一个合法的竞赛图出度序列, 要求构造出原图(原题是求(u, v)有路径的点对数,似乎有不需要构造出原图的方法). 当时我的做法是 直接构造一个网络,跑最大流. 比赛后总觉得这个题有什么神奇的性质,于是搜了一下相关资料: 有一篇关于得分序列的论文:http://www.sciencedirect.com/science/article/pii/0095895

[topcoder]SRM 633 DIV 2

第一题,http://community.topcoder.com/stat?c=problem_statement&pm=13462&rd=16076 模拟就可以了. #include <vector> #include <algorithm> using namespace std; class Target { public: vector <string> draw(int n) { vector<string> result(n,

[topcoder]SRM 646 DIV 2

第一题:K等于1或者2,非常简单.略.K更多的情况,http://www.cnblogs.com/lautsie/p/4242975.html,值得思考. 第二题:http://www.cnblogs.com/lautsie/p/4245242.html BFS和DFS都可以,注意的是,写的时候,可以往que里几个东西一起扔,就不用建立对象了.也可以直接用二维矩阵记录blocked和visited. 剪枝什么的,最基本的是发现其实在步数限制的情况下,棋盘就是有界的了. 第三题:http://ap

Topcoder SRM 648 (div.2)

第一次做TC全部通过,截图纪念一下. 终于蓝了一次,也是TC上第一次变成蓝名,下次就要做Div.1了,希望div1不要挂零..._(:зゝ∠)_ A. KitayutaMart2 万年不变的水题. #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map&