uoj 48 核聚变反应强度 次小公因数

【UR #3】核聚变反应强度

Time Limit: 1 Sec  Memory Limit: 256 MB

题目连接

http://uoj.ac/problem/48

Description

著名核物理专家 Picks 提出了核聚变特征值这一重要概念。

核聚变特征值分别为 x 和 y 的两个原子进行核聚变,能产生数值为 sgcd(x,y) 的核聚变反应强度。

其中, sgcd(x,y) 表示 x 和 y 的次大公约数,即能同时整除 x,y 的正整数中第二大的数。如果次大公约数不存在则说明无法核聚变, 此时 sgcd(x,y)=−1。

现在有 n 个原子,核聚变特征值分别为 a1,a2,…,an。然后 Picks 又从兜里掏出一个核聚变特征值为 a1 的原子,你需要计算出这个原子与其它 n 个原子分别进行核聚变反应时的核聚变反应强度,即 sgcd(a1,a1),sgcd(a1,a2),…,sgcd(a1,an)。

Input

第一行一个正整数 n。

第二行 n 个用空格隔开的正整数,第 i 个为 ai。

Output

一行 n 个用空格隔开的整数,第 i 个表示 sgcd(a1,ai)。

C/C++ 输入输出 long long 时请用 %lld。由于本题数据量较大,建议不要使用 cin/cout 进行输入输出。

Sample Input

4
12450 1 2 450

Sample Output

6225 -1 1 75

HINT

n≤105,ai≤1012

题意

题解:

算法一

对于 n=1 的数据,就是求一个数次大的约数。

众所周知一个数x的约数是成对出现的(d、xd),其中总有一个不超过x√。所以从1到a1−−√地枚举d就能找出所有a1的约数了。排序输出次大的即可。

复杂度:O(a√)
算法二

先找出a1的所有约数,然后枚举i,sgcd(a1,ai)显然也是a1的约数,所以枚举a1的所有约数,找到是ai约数的次大的即可。

复杂度:O(na√)
算法三

考虑分解质因子后:

a=px11px22...pxmm

b=py11py22...pymm

则:gcd(a,b)=pmin(x1,y1)1pmin(x2,y2)2...pmin(xm,ym)m

我们发现,a和b的公约数都一定是gcd(a,b)的约数。那么为了得到次大公约数,只需求出gcd(a,b),再除去一个最小的公共质因子即可。

对a1用O(a1−−√)的时间分解得到O(log(a1))个质因数,每次对于ai,先求出g=gcd(a1,ai),然后枚举a1的每个质因数,找到最小的能整除g那个,设其为p,g/p即为所求。(不存在则为输出−1)

复杂度:O(a√+nlog(a))
一个骗分算法

考虑算法二,我们预先对 a1 的约数们排好序,然后枚举 i,从约数表里每次二分到 gcd(a1,ai)所在位置,再往前枚举,找到第一个能整除ai的即为次大公约数。

虽然复杂度不靠谱,但是对于ai≤1012的范围实际运行速度十分优秀。需要构造针对的数据才能卡住。

还有另一个骗分算法,求出 gcd 然后暴力枚举最小质因子。好多人写这个啊……你们都没意识到复杂度不对么……放你们一马给了 80 分。

(有这种闲心的为啥不写正解啊,你们考虑过 maker 的感受吗!QAQ)

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200001
#define mod 10007
#define eps 1e-9
int Res,Num;char C,CH[12];
//const int inf=0x7fffffff;   //无限大
const int inf=0x3f3f3f3f;
/*

inline void P(int x)
{
    Num=0;if(!x){putchar(‘0‘);puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
*/
//**************************************************************************************
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline void P(int x)
{
    Num=0;if(!x){putchar(‘0‘);puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
ll a[maxn];
ll p[maxn];
int main()
{
    int n=read();
    for(int i=0;i<n;i++)
        scanf("%lld",&a[i]);
    ll tot=0;
    ll x=a[0];
    for(ll i=2;i<=sqrt(x);i++)
    {
        if(x%i==0)
        {
            while(x%i==0)x/=i;
            p[tot++]=i;
        }
    }
    for(int i=0;i<n;i++)
    {
        ll d=gcd(a[0],a[i]);
        int flag=1;
        for(int j=0;j<tot;j++)
        {
            if(d%p[j]==0)
            {
                printf("%lld ",d/p[j]);
                flag=0;
                break;
            }
        }
        if(flag)
        {
            if(d!=1)
                printf("1 ");
            else
                printf("-1 ");
        }
    }

}
时间: 2025-02-01 08:04:28

uoj 48 核聚变反应强度 次小公因数的相关文章

[UOJ #48]【UR #3】核聚变反应强度

题目大意:给你一串数$a_i$,求$sgcd(a_1,a_i)$,$sgcd(x,y)$表示$x,y$的次大公约数,若没有,则为$-1$ 题解:即求最大公约数的最大约数,把$a_1$分解质因数,求出最大公约数,在判断是否可以被整除就行了 卡点:无 C++ Code: #include <cstdio> #include <vector> #define maxn 100010 std::vector<long long> v; int n, sz; long long

UOJ #48.最大矩形面积

[题目描述]: 地面上从左到右并排紧挨着摆放多个矩形,已知这此矩形的底边宽度都为1,高度不完全相等.求在这些矩形包括的范围内能得到的面积最大的矩形,打印出该面积.所求矩形可以横跨多个矩形,但不能超出原有矩形所确定的范围. 如 n = 7, 序列为2 1 4 5 1 3 3 _ _ _ | | _ | | | || | _ _ |H||H| _ _ _ | || | | || | _ |H||H| | || | | | _ | || | _ | || | | | _ |H||H| _ | || |

【UOJ Round #3】

枚举/二分 C题太神窝看不懂…… 核聚变反应强度 QwQ很容易发现次小的公约数一定是gcd的一个约数,然后……我就傻逼地去每次算出a[1],a[i]的gcd,然后枚举约数……这复杂度……哦呵呵... 正解是先找到a[1]的所有质因数啊……然后在刚刚那个算法的“枚举gcd的约数”的时候直接枚举这些质因数就好了…… 1 //UOJ Round3 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #in

开坑UR

会做几道算几道吧…… 开个坑比较能激励自己 强迫症buff+拖延症buff rating神马的?不要在意嘛 没写的都是坑 ~~~~~萌萌哒分割线~~~~~ UR#1 1 缩进优化 2 外星人 3 跳蚤国王下江南 UR#2 1 猪猪侠再战括号序列 2 跳蚤公路 3 树上GCD UR#3 1 核聚变反应强度 2 铀仓库 3 链式反应 UR#4 1 元旦三侠的游戏 只需目测就可以发现,我们可以table[b][a] 然后除了b=1的很长之外,其它都是sqrt(n)以下的 所以可以记忆化,然后b=1时把

CodeForces 55D - Beautiful numbers - [数位DP+离散化]

题目链接:https://cn.vjudge.net/problem/CodeForces-55D Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with

【UOJ Round #1】

枚举/DP+排列组合 缩进优化 QAQ我当时一直在想:$min\{ \sum_{i=1}^n (\lfloor\frac{a[i]}{x}\rfloor + a[i] \ mod\ x) \}$ 然而并不会做啊……一点思路也没有……主要是后面那个取模非常难受…… 其实正解有点逆向思维的感觉:$ans=\sum_{i=1}^n a[i] - max\{ \sum_{i=1}^n \lfloor \frac{a[i]}{x}\rfloor *(x-1) \} $ 也就是先将a[i]全部加起来,然后再

【UOJ Round #8】

A 一道不错的题,虽然大家都觉得是水题,然而蒟蒻我想出来的好慢……Orz alpq 发现其实就是一个网格图,每一个大块都是同一颜色……横纵坐标互不干扰…… 1 //UOJ Round #8 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8

Js判断密码强度并显示提示信息

用javascipt实现的Ajax判断密码强弱的功能,大多数有用户注册功能的网站,都会有这么一个功能,作为WEB程序员,应该会写这种小模块哦,不懂的就看下这个例子,觉得挺简单,当初帮助了不少人学会了密码强度的检测. 表单部分,用来显示密码框和密码强度提示信息: <form name=form1 action="" > 请设置密码:<input type="password" size="10" onKeyUp="pwS

UOJ#179. 线性规划[模板]

传送门 http://uoj.ac/problem/179 震惊,博主竟然还不会线性规划! 单纯形实在学不会啊……背个板子当黑盒用…… 学(chao)了NanoApe dalao的板子 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 const d