暑假选拔赛

以难度顺序排列

1.摸鱼王的2468复读机

在这里插入图片描述

分析

有规律的,除去第一位2的0次方个位数为1,其余以2 , 4,8 , 6为循环

代码

#include<iostream>
using namespace std;

int main() {
	long long n;
	cin>>n;
	int ans;
	if(n==0)
		ans = 1;
	else {
		switch(n%4) {
			case 0: ans = 6;
			break;
			case 1: ans = 2;
			break;
			case 2: ans = 4;
			break;
			case 3: ans = 8;
			break;
		}
	}
	cout<<ans<<endl;
	return 0;
}

2.签到题

分析

其实输出结果就是printf中的表达式,随便尝试一下就可以发现规律就是1,-1重复的循环,所以唯一的问题就是n过大,会超时

代码

#include<iostream>
using namespace std;

int main() {

	long long n;
	scanf("%lld",&n);

	if(n%2==0)
		cout<<-1<<endl;
	else
		cout<<1<<endl;
	return 0;
} 

3.阶乘

在这里插入图片描述

分析

对于所有数,能够相乘得出10的倍数才能使结果的末位增加0,所以5成为一个非常重要的数字,对于每一个5,都需要一个2和它配对相乘才能得出10,所以所有2的倍数(2,4,6,8)都能够担此重任,把所有数分成5个一组,而对于阶乘而言,每一个5之前都会有至少两个2的倍数,所以一定够用。
需要注意的地方在于一些比较特殊的数字,例如25=5 * 5,这个数字能够拆分成为两个5,所以可以增加两个0,而50 = 2 * 5* 5也可以增加两个0,125 = 5 * 5 * 5,可以增加三个0,所以对于每一个数n!末尾的0应该表示为f(n) = n/5 + f(n/5),并且循环嵌套。

代码

#include<iostream>
using namespace std;

int main() {
	int n;
	int count=0;
	cin>>n;
	while(n) {
		n /= 5;
		count += n;
	}
	cout<<count<<endl;
	return 0;
}

4.ff爱组合数

在这里插入图片描述

分析

问题其实已经给出了公式,最复杂的部分就是怎么解决时间复杂度和答案溢出的问题,直接两个for循环嵌套就可以解决,然后计算结果的时候多多mod取余,以防溢出,虽然题目中好像没有这种情况。

代码

#include<iostream>
#include<string.h>
using namespace std;
const long long MOD = 1e9 + 9;
long long num[2002][2002];
void fun();

int main() {
	int T;
	memset(num,0,sizeof(num));
	cin >> T;
	fun();
	while (T--) {
		int n, m;
		cin >> n >> m;
		cout << num[n][m]<< endl;
	}
}
void fun() {
	for (int i = 0; i <= 2001; i++) {
		num[0][i] = 0;
		num[i][0] = 1;
	}
	for (int i = 1; i <= 2001; i++) {
		for(int j = 1; j <= i; j++) {//因为i一定大于等于j,结束条件减少无意义的计算 
			num[i][j] = (num[i-1][j]%MOD + num[i-1][j-1]%MOD) % MOD;
		}
	}
}

5.合并滑稽

在这里插入图片描述

分析

是一道贪心策略的题目,我觉得贪心没有固定的解题模式,就是一种理解方式。
本题的意图就是不断把一组数排序,然后取最小的两个数相加得出一个新的数放入数列中,之前的两个数抛去,并将相加的结果累加得出答案。
根据分析,其实用最简单的数组就能写,但是数据最大开到了10000,我算了一下,时间复杂度大概是10的8次方,亿级别以上基本不可能过,但是学校的平台上数据水了竟然过了。
所以必须使用优先队列,这里涉及STL内容(以后总结的话会更新)。首先将每个元素压入小根堆,在循环的时候不断的取头上的值,取两个作为最优值(a,b),最后再弹掉。结果就是不断累加两个元素(a,b),最后再把此次的和再压入小根堆。

错误代码

这是会超时的代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int num[10005];

int main() {
	int n;
	cin >> n;
	//memset(a,0,sizeof(a));
	for (int i = 0; i < n; i++) {
		cin >> num[i];
	}
	long long mx = 0;
	while (n > 1) {
		sort(num, num+n);
		num[0] += num[1];
		mx += num[0];
		n--;
		for (int i = 1; i < n; i++) {
			num[i] = num[i+1];
		}
	}
	cout <<mx<<endl;
	return 0;
}

AC代码

#include<queue>
#include<iostream>
#include<stdio.h> 
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;//优先队列定义小根堆


int main(){
	int n,x;
	int ans=0;//一定记得初始化,因为没初始化卡了两次
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x;
        q.push(x);
    }
    while(q.size()>=2){//终止条件
        int a=q.top();//取头最优值
        q.pop();//丢弃 
        int b=q.top();
        q.pop();
        ans += a+b;//最优值来源
        q.push(a+b);//压入
    }
    printf("%d\n",ans);//输出
    return 0;
}

6.约数的个数

在这里插入图片描述

分析

这道题的意图就是求出1-N中所有数的约数个数,并依次相乘一个常数,最后求出相加的和,且为了防止数字过大溢出要约1e15,。
求约数可以使用数论中提到的方法–筛法求解,

代码

在这里插入代码片

7.猜猜在哪里

描述

有一个很有意思的魔术

桌子上有从左到右编号为1到n的n顶不透明的帽子,一开始只有1号帽子下面有一只兔子,魔术师会依次交换其中的m对帽子,也就是说每次把从左往右的第x个帽子和第y个帽子交换,其中x, y不相同,帽子下的兔子也会跟着帽子移动。

由于魔术师神奇的手法,作为观众的你没有看到魔术师的部分交换操作,但你按顺序记下了一部分不一定连续的交换操作。对于每个你没看到的交换操作,我们假设魔术师会等概率地选择两个位置不同的帽子交换,请问所有操作结束以后,兔子在从左到到右第1, 2, …, n号帽子底下的概率分别是多少?
在这里插入图片描述

分析

代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值