牛客寒假第一场训练赛

比赛链接
题解
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;
}

猜你喜欢

转载自blog.csdn.net/cosx_/article/details/113562853