2020第十一届国赛B组题解

C.阶乘约数

在这里插入图片描述

解题思路

1.根据数学公式:
	任意一个正整数 X 都可以表示成若干个质数乘积的形式,即 X = p1^α1 ∗ p2@α2 …… ∗ pk^αk
    约数个数 = (a1 + 1)(a2 + 1)……(ak + 1)
2.用p[i]表示n中的素数约数i的a1次幂;

代码展示

#include<bits/stdc++.h>
using namespace std;

int p[200];//p
void init(){
	for(int i=2;i<=100;i++){
		int n=i;
		for(int j=2;j<=n/j;j++){//保证得到的结果是质数,因为 2~n/j都无法整除 
			while(n%j==0){
				n/=j;
				p[j]+=1;
			}	
		}
		if(n>1)p[n]+=1;
	}
}
int main(){
	init();
	long long ans=1;
	for(int i=2;i<=100;i++){
		if(p[i])ans*=(p[i]+1);
		cout<<ans<<endl;
	}
	cout<<ans<<endl;
   return 0;
   
}

总结

1.就是一个数学公式;
2.其实做题的时候并非毫无头绪,也想到肯定会与质因数有关,但不了解具体关系~~~

D.本质上升序列

在这里插入图片描述

解题思路

1.由于字符串有200位,DFS遍历不可行;
2.用dp处理,与LIS类似,num[i]记录以s[i]结尾的递增子串个数;
3.在LIS中,当s[i]>s[j]使,num[i]=max(num[i],num[j]+1)是为了求出最长的子串;类比可得动态规划方程 num[i]+=num[j];
4.当s[i]==s[j]时,num[i]-=num[j],下面画图解释;
(图待完善~~~)

在这里插入图片描述

代码展示

#include<bits/stdc++.h>
using namespace std;
/*

*/
string s;
int num[100];//以i结尾的递增子串个数 
int main(){
	string s;
	cin>>s;
	int l=s.size();
	int ans=0;
	for(int i=0;i<l;i++){
		num[i]=1;
		for(int j=0;j<i;j++){
			if(s[i]>s[j])
				num[i]+=num[j];
			else if(s[i]==s[j])
				num[i]-=num[j];
				//!!!
		}
		ans+=num[i];
	//	cout<<"num[] = "<<num[i]<<endl;
	}
	cout<<ans<<endl;
	return 0;
}

E.玩具蛇

在这里插入图片描述

解题思路

1.玩具蛇的起点A可以在1~16的任何一个位置;
2.从A所处的(x,y)出发,暴力搜素A~P的位置即可,因为A的位置不一样,所以不会重复;

代码展示

F.皮亚诺曲线

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解题思路

代码展示


H.答疑

解题思路

假设排序之后的每人的si,ai,ei;
那么就有每人答疑时间为:
	1   s1+a1
	2   s1+a1+e1 + s2+a2
	3	s1+a1+e1 + s2+a2+e2 + s3+a3
	4   ~~~~~
	n   ~~~~~
那么不难看出,前面的学生的用时总和出现次数很多,所以我们只要保证前面的学生的总用时尽可能小,那么总答疑时间就最小。

代码展示

就不展示了,简单的结构体排序~~

J.质数行者

解题思路

1.题目很简单,就是简单的搜索;
2.用BFS从(1,1,1)开始遍历,记录队列中(5,6,1)出现的次数,即为路径数
3.因为始终是向南、东、上走,不会回去,所以不需要判断节点是否访问。

代码展示

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
思路:
5 6 1
3 4 1 1 2 1	

*/
struct node{
	int x,y,z;
};
bool G[1005][1005][1005];
bool Prim(int x){
	if(x<2)return false;
	for(int i=2;i*i<=x;i++){
		if(x%i==0)return false;
	}
	return true;
}
vector<int>prim;
int maxp;
void init(){
	for(int i=2;i<=maxp;i++){
		if(Prim(i))prim.push_back(i);
	}
}
int n,m,k;
ll BFS(){
	ll ans=0;
	queue<node>q;
	node temp;
	temp.x=1,temp.y=1,temp.z=1;
	q.push(temp);
	while(!q.empty()){
		temp=q.front();
		q.pop();
		if(temp.x==n&&temp.y==m&&temp.z==k){
			ans+=1;
			ans=ans%1000000007;
			continue;
		}
		for(int i=0;i<3;i++){
			for(int j=0;j<prim.size();j++){
				bool flag=0;
				node f;
				f.x=temp.x;f.y=temp.y;f.z=temp.z;
				if(i==0&&temp.x+prim[j]<=n){//x
					f.x=temp.x+prim[j];
					flag=1;
				}
				else if(i==1&&temp.y+prim[j]<=m){//y
					f.y=temp.y+prim[j];
					flag=1;
				}
				else if(i==2&&temp.z+prim[j]<=k){//y
					f.z=temp.z+prim[j];
					flag=1;
				}
				if(!G[f.x][f.y][f.z]&&flag){
						q.push(f);
				//cout<<f.x<<" "<<f.y<<" "<<f.z<<" "<<ans<<endl;
				}
				
			}
		}
	}
	return ans;
}
int main(){
	cin>>n>>m>>k;
	maxp=max(max(n,m),k);
	init();
	for(int i=0;i<2;i++){
		int a,b,c;
		cin>>a>>b>>c;
		G[a][b][c]=1;
	}
	ll ans=BFS();
	cout<<ans<<endl;
   return 0;
   
}

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
国赛 终于到了国赛的日子,不过凑巧的是当时本人学院上学期疫情的考试安排在的本学期开始,这意味着我要开始边备考边建模,顶着挂科的压力放肆复习。 选的话,之前说过了果断选的新颖B(穿越沙漠)。 简单说下我们的思路: 我们对赛的理解是这情景非常具体,数据需要少,感觉三问都是优化模型,而且需要很强的编程。 首先我们分析目,对游戏规则摸清楚,没有急着建模。 涉及到路线、事件的选择,使用 0-1 变量等定义模型。 最短路径用Floyd算法或者基本可以数出来,考察的是最优路径以及路径前对资源的购买(收益最大)。 第一问: 在第一关和第二关的探险过程中,运用初始的资金对于资源进行合理的分配,可以通过线性规划,确定好在未来一段时间的消耗与收益,制定好合理的规划,通过 MATLAB 计算出需要使用的资源。经过多次训练对比,最终计算出最优策略,对比资金数量。因为不确定答案是否正确,后来我们又用excel表格进行了推导,最后得到是12730,与优秀论文中的12760相比小了30块,估计大概因为这个答案的问,没有国一。 第二问: 第二问与第一问相比提升了难度,如果玩家在进行策略安排的时候, 不知道天气的状况那么小伙伴们可以自己商讨给出何种方案,比如多买水,多买食物等等方法,再这之后通过选择最优路径进行合理的方法选择并讨论,具体的解决方法是通过编程和启发式算法的excel解决的。 第三问: (1) 对于n 名相同的初始资金,且同时从起点出发的玩家来说,游戏规则需要进一步注意规范,为了保证多方共赢,在天气状况已知的情况下, 可以通过先前 MATLAB 中的神经网络算法算出的最优旅行路线,计算多次的结果进行对比,保证不会出现重复的状况, 剔除掉重复出现的次数。因为天气状况已知,所以相对比较好安排合理的路线,对于安排好的路线分别进行编号,再依次进行合理的计算,最终确定结果,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高冷小伙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值