2021牛客寒假算法基础集训营1
比赛链接
I.限制不互素对的排列
题目描述
输入一个数 \(n\) ,请构造一个长度为 \(n\) 的排列,使得其中正好有 \(k\) 对相邻的数gcd(最大公约数)大于 1 。 排列是指 1 到 \(n\) 一共 \(n\) 个数,每个数都出现过且仅出现过 1 次。例如, \(\{1,3,2,5,4\}\) 是一个排列,而 \(\{1,3,4,5,3\}\) 、 \(\{1,2,4\}\) 则不是排列
输入描述:
两个整数 \(n\) 和 \(k\), 用空格隔开。
\(2 \leq n \leq 100000,0 \leq k \leq n / 2\)
输出描述:
如果不存在可行的构造方案, 输出 \(-1\) 。
否则输出一行 \(n\) 个数, 用空格隔开。如果有多组可行的构造方案, 输出任意一组即可。
解题思路
构造
所有连续的自然数互质,所有连续的奇数互质
由于 \(k\leq n/2\),即 \(k\) 不算很大,可以分两种情况”
-
\(k
,可以先输出 \(k+1\) 个偶数,再输出最后输出的偶数后面的所有数,然后再输出前面的奇数 -
\(k=n/2\),这时即使算上所有的偶数还少了一个,可以将 \(6\) 和 \(3\) 放在后面,然后再输出那些剩余的奇数
-
时间复杂度:\(O(n)\)
代码
// Problem: 限制不互素对的排列
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/30716/I
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair PII;
typedef pair PLL;
template bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=100005;
bool v[N];
int n,k;
int main()
{
cin>>n>>k;
if(n<6&&k==n/2)
{
puts("-1");
return 0;
}
if(k
J.一群小青蛙呱蹦呱蹦呱
题目描述
有\(n\)个格子,每个格子里有一个数,\(1,2,3,4...n\)
牛牛放出无穷只青蛙。
第一只青蛙的路线是:1->2->4->8->16->....
第二只青蛙的路线是:1->3->9->27->81->....
第三只青蛙的路线是:1->5->25->125....
第四只青蛙的路线是:1->7->49........
。。。。。。
用数学语言描述,第 \(i\) 只青蛙的路线是首项为\(1\),公比为\(p(i)\) 的等比数列,其中\(p(i)\) 代表第\(i\) 个素数。
当青蛙跳到一个格子上,如果这个格子上面有一个数,青蛙就会把这个数吃掉。
牛牛想知道,所有没有被吃掉的数的lcm(最小公倍数 ,Least common multiple)是多少?
由于这个lcm可能非常大,请输出它对\(10^9+7\) 取模的值。
输入描述:
一个正整数\(n\)
\(1\leq n \leq 1.6 \times 10^8\)
输出描述:
如果所有数都被吃掉了,请输出一个字符串"empty"
否则输出所有没有被吃掉的数的lcm,对\(10^9+7\) 取模
示例1
输入
7
输出
6
说明
数字 1 可以被所有青蛙吃掉;
数字 2 可以被第 1 只青蛙吃掉;
数字 3 可以被第 2 只青蛙吃掉;
数字 4 可以被第 1 只青蛙吃掉;
数字 5 可以被第 3 只青蛙吃掉;
数字 6 无法被吃掉;
数字 7 可以被第 4 只青蛙吃掉。
所以剩下的数字只有一个 6 ,所有数的 lcm 为 6
示例2
输入
123456789
输出
539747460
解题思路
思维
多个数的最小公倍数为所有数分解质因数,对应幂次最大的质因数幂次方的乘积
考虑每个质因数的贡献,对于一个质因数 \(p\) 来说,\(p=2\) 时,显然要找到 \(3\times 2^k\leq n\) 最大的 \(k\),\(p>2\) 时,要找到 \(2\times p^k\leq n\) 最大的 \(k\)
- 时间复杂度:\(O(n)\)
代码
// Problem: 一群小青蛙呱蹦呱蹦呱
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/30716/J
// Memory Limit: 2097152 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair PII;
typedef pair PLL;
template bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=8e7+5,mod=1e9+7;
int prime[N],m,n;
bool v[N];
void primes(int n)
{
for(int i=2;i<=n;i++)
{
if(!v[i])prime[++m]=i;
for(int j=1;prime[j]<=n/i;j++)
{
v[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
int main()
{
primes(N-1);
cin>>n;
if(n<6)
{
puts("empty");
return 0;
}
int res=1;
for(int i=2;i<=m;i++)
{
if(2*prime[i]>n)break;
int t=1;
while(1ll*t*prime[i]<=n/2)t*=prime[i];
res=1ll*res*t%mod;
}
int t=1;
while(1ll*t*2<=n/3)t*=2;
res=1ll*res*t%mod;
cout<