补:2021牛客寒假算法基础集训营1

比赛跑路太早,一听题解就好气,感觉本不该这么菜,所以以后跑路会慢些 !
代码参考了好多人,雨巨,大佬xxx,感谢。
大部分代码是参考 雨巨,特别感谢QwQ
水平有限,题解供参考
官方题解:https://ac.nowcoder.com/discuss/593200
目前已经写的是A,B,F,H,I,J(2021/2/2)

A 串

题目链接:https://ac.nowcoder.com/acm/contest/9981/A
题目思路:分析如图:
在这里插入图片描述

AC代码

	#include<iostream>
	
	using namespace std;
	
	const int N = 2e6 + 10;
	const int p = 1000000007;
	
	int n;
	long long f[N][3];
	
	int main()
	{
		cin >> n;
		f[1][1] = 1;f[1][2] = 25;
		long long ans = 0;
		for(int i = 2;i <= n;i ++)
		{
			f[i][0] = (f[i - 1][0] * 26 % p + f[i - 1][1]) % p;
			f[i][1] = (f[i - 1][1] * 25 % p + f[i - 1][2]) % p;
			f[i][2] = f[i - 1][2] * 25 % p;
			ans = (ans + f[i][0]) % p; 
		}
		cout << ans;
		return 0;
	}

参考雨巨 ,感觉空间上可以继续优化, 这个日后更新,flag ++;
空间上优化,列出状态转移方程。

f[i] =26 ^ (i - 1) - 25 ^ (i - 1) + 25 * f[i - 1]

why?
分俩两种:第一种,如果前面包含us,直接随便上一个字母.
f[i] = f[i - 1] * 26; ①
第二种,如果前面不包含us,但是包含u,上一个s,就可以。
方案数 = 26 ^ (i - 1) - 25 ^ (i - 1) - f[i - 1];②

① + ②,得状态转移方程。
虽然空间复杂度降低了不少,但是 26 的 (i - 1) 次方 ,25 的 (i - 1) 次方,这个需要快速幂求解。

B 括号

题目链接:https://ac.nowcoder.com/acm/contest/9981/B
题目思路:比赛的时候只过了 80 80 80%,debug了好久终于只过 75 75 75%(喵喵喵?)
AC代码

#include<cmath>
#include<iostream>

using namespace std;

int main()
{
	int k;
	cin >> k;
	int a = k / 50000;
	for(int i = 0;i < a;i ++)cout << "(";
	int b = k % 50000;
	for(int i = 50000;i >= 1;i --)
	{
		if(i == b) cout << "(";
		cout << ")";
	}
	return 0;
}

OK,下面来分析为什么我的又臭又长 的代码,为什么只能过 75 75 75%

#include<iostream>
#include<cmath>

using namespace std;

int main()
{
	int n;
	cin >> n;
	int x = sqrt(n);
	//定义d是差了几个 
	int d = n - x * x; 
	// 0 特殊判断一下 
	if(n == 0)puts(")(");
	else if(d == 0)
	{
		//d == 0 说明正好左边 x 个 右边 x 个;
		for(int i = 0;i < x;i ++)cout << "(";
		for(int i = 0;i < x;i ++)cout << ")"; 
	}
	else if(n < 99999)
	{
		cout << "(";
		for(int i = 0;i < n;i ++)cout<< ")";
	}
	else {
		for(int i = 0;i < x;i ++)cout << "(";
		for(int i = 0;i < x - d;i ++)cout << ")";
		cout << "(";
		for(int i = 0;i < d;i ++)cout << ")";
	}
	return 0;
} 

错在了最后一个 e l s e else else 这里,思考一下,如果是 15 15 15(虽然15 不会到最后一个 e l s e else else,但是这里是举例子)的话, s q r t = 3 sqrt = 3 sqrt=3,意思是后面剩下 3 3 3个反括号,但是 d d d 缺差了 6 6 6,凑不出来。

C 红和蓝

D 点一成零

E 三棱锥之刻

F 对答案一时爽

题目链接:https://ac.nowcoder.com/acm/contest/9981/F
题目思路:最小一定是 0 0 0,最大是 n n n + 选择重复的个数。
AC代码

#include<bits/stdc++.h>
#define PI acos(-1)
#define endl "\n"
#define mm(a, b) memset(a, b, sizeof(a))
#define debug freopen("1.in", "r", stdin), freopen("1.out", "w", stdout);
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int , int> PII;

const int N = 200;

int n; 
char a[N],b[N];

int main()
{
	ll res = 0;
	cin >> n;
	for(int i = 0;i < n;i ++)cin >> a[i];
	
	for(int i = 0;i < n;i ++)
	{
		cin >> b[i];
		if(a[i] == b[i])res ++;
	}
	res = res + n;
	//for(int i = 0 ;i < n ;i ++)cout << a[i] << endl;
	cout << res << " " << "0" << endl;
	return 0;
}

G 好玩的数字游戏

H 幂塔个位数的计算

题目链接:https://ac.nowcoder.com/acm/contest/9981/H
题目思路

思路1 :欧拉降幂(现在不会,日后会学,flag++)
思路2:找规律

思路2分析:
如果个位是0,幂多少次个位都是0。
如果个位是1,幂多少次个位都是1。
如果个位是2,2 4 6 8·····循环。
如果个位是3,3,9,7,1······循环。
如果个位是4,4,6·····循环。
如果个位是5,幂多少次都是5。
如果个位是6,幂多少次都是6。
如果个位是7,7,9,3,1······循环。
如果个位是8,8,4,2,6······循环。
如果个位是9,9,1······循环。

所以,如果是0 , 1, 5, 6,特判即可。

如果是 2 : a^a^ ,只需要判断 a % 4的大小,因为a结尾是2,所以a一定是个偶数, % 4只有两种结果,一种是2,一种是0,如果是2,输出4,如果是0,输出8.
如果 是 a^x^,x = a^a^,那么只有一种情况,因为 a 是个偶数,那么a 的 a 次方一定能整除4.

8则同2:如果个位是8,a % 4 可以取 0,2。 如果是 a^a^ % 4, 一定是0。

如果是3:a % 4 ,要么取3,要么取1。如果a % 4 = 3,那么如果a 幂了 奇数个 a 对 4 取模,答案依然是3,同理:a % 4 = 1,那么如果a 幂了 奇数个 a 对 4 取模,答案依然是1。

7则与3分析相似,但是相反:如果a % 4 = 3,那么如果a 幂了 奇数个 a 对 4 取模,答案是1·······


现在还剩下4,9.
如果是4的话,因为4是偶数,% 2 一定是0,始终是6.
如果是9,% 2 一定是 1,始终是9.


OK分析完毕,学欧拉降幂的奇怪动力增加了。

AC代码

#include<iostream>
#include<cstring>
#include<string.h>
using namespace std;

int a, b;
string s1, s2;

int main()
{
	cin >> s1 >> s2;
	// 如果是 1次方,直接输出个位。 
	if(s2 == "1"){cout << s1[s1.size() - 1];return 0;}
	
	a = s1[s1.size() - 1] - '0';
	b = ((s1[s1.size() - 2] - '0') * 10 + (s1[s1.size() - 1] - '0')) % 4; 
	 
	if(a == 0 || a == 1 || a == 5 || a == 6 || a == 9)cout << a;
	
	if(a == 4) cout << 6;
	
	if(a == 2 || a == 8)
	{
		if(s2 == "2" && b != 0) cout << 4;
		else cout << 6;
	}
	
	if(a == 3)
	{
		if(b == 1) cout << 3;
		else cout << 7;
	}
	
	if(a == 7)
	{
		if(b == 3)cout << 3;
		else cout << 7;
	}
	return 0;
}

I 限制不互素对的排列

题目链接:https://ac.nowcoder.com/acm/contest/9981/I
题目思路:确实,在限定了 k < = n / 2 k <= n / 2 k<=n/2的情况下,题目简单了许多,只需要把情况分成两种,第一种 k < n / 2 k < n / 2 k<n/2 第二种 k = n / 2 k = n / 2 k=n/2,第一种,只用部分偶数就能解决问题,但是在第二种的时候可以用6 后面接 3 来凑到 n / 2 n / 2 n/2,当 n < 6 n < 6 n<6 的时候,只能由偶数来凑 k 对,如果凑不到,就返回 − 1 -1 1.
AC代码

#include<iostream>

using namespace std;

int n, k;

int main()
{
	cin >> n >> k;
	if (n < 6 && k == n / 2)
    {
        cout << -1;
        return 0;
 
    }
     if (k < n/2)
   	{
		int i = 2;
        for(int j = 0;j < k + 1;j ++,i = i + 2) cout << i << " ";
        i = i - 2;
        for(int j = i + 1;j <= n;j ++)cout << j << " ";
        
        for(int j = 1;j <= i;j = j + 2) cout << j << " "; 
     }
	else
	{
		 int i = 8;
        for (int j = 0; j < k - 2;  j ++, i = i + 2) cout << i << " ";
        
        cout << 2 <<' '<< 4 <<' '<< 6 <<' ';
        
        cout << 3 <<' '<< 1 <<' ';
        for (int i = 5; i <= n; i = i + 2) cout << i <<" ";
	} 
	return 0;
} 

J 一群小青蛙呱蹦呱蹦呱

题目链接:https://ac.nowcoder.com/acm/contest/9981/J
题目思路:明天再写,数学好难QAQ。
AC代码

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 160000000; 
const int p = 1000000007;

int n;
int primes[N], cnt;
bool st[N];

long long ksm(int a, int b)
{
    long long ans= 1, t= a;
    while(b)
    {
        if (b & 1) ans = ans * t % p;
        t = t * t % p;
        b >>= 1;
    }
    return ans;
}

long long solve(int x)
{
	if (x == 2)
        return ksm(2, floor(log(n/3)/ log(2)));
    return ksm(x, floor(log(n/2)/ log(x)));
}

int main()
{
	cin >> n;
	ll res = 1;
	for (int i = 2; i <= n / 2; i ++ )
    {
        if (!st[i])
		{
			//cout << ksm(2,i) <<endl; 
			primes[cnt ++ ] = i;
			res = (res * solve(i)) % p;
		}
        for (int j = 0;primes[j] <= n / i * 2; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
	if(res == 1) cout << "empty";
	else cout << res;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值