持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
2022年第三届辽宁省大学生程序设计竞赛——F-互质
F-互质
题目描述
琴·古恩希尔德,蒙德城西风骑士团代理团长,四风守护中的南风之狮。身为西风骑士团的代理团长,琴一直忠于职守,为人们带来安宁。虽然并非天赋异禀,但通过刻苦训练,如今的她已然能够独当一面。当风魔龙的威胁开始临近,这位可靠的代理团长早已做好了准备,誓要守护蒙德。
雷泽,住在蒙德地区奔狼领,远离城市与人群,和狼一同生活的少年。直觉锐利,身姿迅捷。
琴团长这几天准备教一下雷泽数学,问了雷泽一个关于互质的问题。
互质是一个数学概念,两个数互质是指两个数的共同因子只有1。
琴团长提出了T次询问,每次询问给出一个正整数n,询问雷泽是否存在一个正整数x,满足x大于等于n/4向上取整,小于等于n/2向下取整,且x与n互质。
雷泽并不会数学,于是便向你求助。
输入描述:
第一行只有一个正整数T,表示询问的数量。 接下来的T行,每行一个正整数n,表示询问的数字。
1 <= T <= 10^6,4 <= n <= 10^16
输出描述:
本题采用special judge。
输出一共T行,每次询问分别输出一个整数,如果存在一个满足上述条件的x,输出这个x,否则输出-1。
输入
2
6
9
输出
-1
4
问题解析
一开始想筛出全部的质数,然后根据区间{n/4,n/2}来二分找在区间中的质数,但是后来发现n太大了,而且质数也不一定就是正确答案,正确答案还有可能是非质数。
后面又想出,当n很小时,区间{n/4,n/2}不会太大,我们可以直接枚举里面的元素i,当gcd(i,n)==1时,i就是答案。
但当n很大时,我们显然不能这么玩,因为n很大时,区间{n/4,n/2}也会很大,比如当n是4e15时,区间就是{1e15,2e15},如果枚举,我们要枚举1e15个数。
但是,很明显不会有很长的一段连续数都不与n互质。因为一般来说连续100个数左右肯定会有质数的出现,那么我们不用傻乎乎的枚举到从n/4枚举到n/2。我们枚举n/4到n/4+100就行。
(100要是觉得多了,50也可以)
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 1e9 + 7;
void solve()
{
int n;
cin >> n;
int l = n / 4, r = n / 2;
if (n % 4 != 0)l++;
for (int i = l; i <= min(r, l + 100); i++)
{
if (gcd(i, n) == 1)
{
cout << i << endl;
return;
}
}
cout << -1 << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}