比赛链接
题解
B题
构造题
先找构造括号效率比较高的方法
(()) 这种括号里面套括号效率比较高而且合法
所以思路就是对所给整数开方,剩余的零头我们用枚举的方法。
但是对于一些数据直接用开方得到的数x构造的话,会导致零头太小,不好构造零头
第一步构造的是一个对称的括号,有x个左括号,如果零头小于x的话,就不好构造零头。所以如果零头小于x的话,就选择把x缩小1,再构造零头就可以了。
代码如下
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
typedef long long ll;
const int Max = 5000;
ll n, k;
int p[Max],v[Max],cnt;
void xxs()
{
for(int i = 2; i <= Max; ++i)
{
if(!v[i]) p[cnt++] = i;
for(int j = 0; p[j] * i < Max; ++j)
{
if(p[j] * i < Max) v[p[j] * i] = 1;
if(i % p[j] == 0) break;
}
}
}
void work()
{
if(k == 0) {
cout << ")(" << endl;return ;
}
ll x = (int)sqrt(k);
ll sum = k - x * x;
ll a = sum - x;
if(a <= 0)
{
x--;
sum = k - x * x;
a = sum - x;
}
for(ll i = 1; i <= x; i++) printf("(");
for(ll i = 1; i <= x; i++) printf(")");
for(ll i = 1; i <= a; ++i) printf("(");
printf(")");
cout << endl;
}
int main()
{
cin >> k;
work();
return 0;
}
I题
也是构造题
首先观察数据范围
所要求构造的对数, 是小于n/2的,这可以联想到用奇偶数构造。
由于n个偶数只能构造 n - 1 对
所以要分两种情况 k<=n/2 和 k == n/2;
其次第二种情况我们要用 3 的倍数来构造(用偶数构造其实是用的2的倍数,如果k没有限制范围,还可以用 5 的倍数等等,即质因数的倍数来构造),而用一次3的倍数构造,就可以把6拿出来,因为6也是2的倍数并且是同时为2和3倍数中最小的。
#include<bits/stdc++.h>
using namespace std;
int n,k;
int main()
{
cin >> n >> k;
if(k < n / 2)
{
for(int i = 1; i <= k + 1; ++i)
printf("%d ", i * 2);
for(int i = 1; i <= k + 1; ++i)
printf("%d ", i * 2 - 1);
for(int i = 2 * k + 3; i <= n; ++i)
printf("%d ", i);
}
else
{
if(n < 6) {
printf("-1");return 0;
}
for(int i = 1; i <= k; ++i)
if(i * 2 != 6) printf("%d ", i * 2);
printf("6 3 ");
for(int i = 1; i <= n; i += 2)
if( i != 3) printf("%d ", i);
//for(int i = 1; i <= n; ++i)
// if( i*2-1 != 3) printf("%d ", i * 2 - 1);
// if(n % 2 != 0) printf("%d",n);
// 这个输出方式很容易忽略掉最后一个n导致出错,如果是奇数,n不会输出,所以要打个补丁
}
return 0;
}
J题
最大的一个质因子就是 满足 2 * Pi(一次方) <= n / 2
关于求剩余数的LCM
由唯一分解定理
2 * 2 * 2 * 3 * 3 与 2 * 2 * 3 * 3 * 3 这两个数的LCM
就是 取这两个数 2的最高次幂 与 3的最高次幂的乘积
n个数的LCM就是图中的结论
#include<bits/stdc++.h>
using namespace std;
#define N 80010000
#define ll long long
int num[N], prim[5000060];
int pn = 0;
const ll mod = 1e9 + 7;
void table()
{
memset(num, -1, sizeof(num));
for(int i = 2; i < N; i++)
{
if(num[i]) prim[pn++] = i;
for(int j = 0; j < pn && 1LL*i*prim[j] < N; j++)
{
num[i*prim[j]] = 0;
if(i % prim[j] == 0) break;
}
}
}
int main()
{
table();
ll res = 1, i, n;
cin >> n;
if(n < 6) {
cout << "empty";return 0;}
for(i = 1; prim[i] <= n / 2; i++)// 从质数3开始遍历求直到 Pi
{
ll p = prim[i], temp = 1;
while(temp * p <= n / 2) temp *= p;// 要让k最大,那么就要乘以最小的质数2
//因为我们只需要求每个质数的最高次幂
res = res * temp % mod;
}
ll temp2 = 1;
while(temp2 * 2 <= n / 3) temp2 *= 2; // 单独求一下2的最高次方
res = res * temp2 % mod;
cout << res;
}