2023牛客寒假算法基础集训营6(题解及经验总结)

A 阿宁的签到题(简单题)

通过率:3035/3878

因代码打错wa了一发!!! 
注意else if的含义:若有一个满足条件,则后面的不再执行 !!!

赛场AC代码:

#include
#include
#define int long long
using namespace std;

signed main(){
	int n;
	cin>>n;
	if(n>=1&&n<=7){
		cout<<"very easy";
	}else if(n>7&&n<=233){
		cout<<"easy";
	}else if(n>233&&n<=10032){
		cout<<"medium";
	}else if(n>10032&&n<=114514){
		cout<<"hard";
	}else if(n>114514&&n<=1919810){
		cout<<"very hard";
	}else{
		cout<<"can not imagine";
	}
	
	return 0;
} 

B 阿宁的倍数 

通过率:486/2909

因子、判质数

思路:定义一个桶u[N]来表示每个数的因数的个数,定义v[N]来表示截止到a[i]时,前i个数的因数a[i]的个数(前缀和),用总的因数u[a[i]]减去前i个数中因数a[i]的个数,即为第i个数之后因数a[i]的个数

AC代码:

#include
#include
#define int long long
using namespace std;

const int N=200005;
int a[2*N],u[N],v[2*N];
signed main(){
	int n,q,op,x;
	cin>>n>>q; 
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j*j<=a[i];j++){
			if(a[i]%j==0){
				u[j]++;
				if(j*j!=a[i]){
					u[a[i]/j]++;
				}
			}
		}
		v[i]=u[a[i]];
	}
	for(int i=0;i>op>>x;
		if(op==1){
			n++;
			a[n]=x;
			for(int j=1;j*j<=x;j++){
				if(x%j==0){
					u[j]++;
					if(j*j!=x){
						u[x/j]++;
					}
				}
			}
			v[n]=u[x];
		}else{
			cout<

C 阿宁的大背包(简单题)

通过率:1884/5202

结论题!!!

杨辉三角???经典向量点积结论???

我的思路:直接构建形如:1 3 5 7 9...10 8 6 4 2的数组,该数组即能合成最大背包

赛场AC代码:

#include
#include
#define int long long
using namespace std;

const int N=1005;
const int mod=1e9+7;
int a[N],b[N];
signed main(){
	int n;
	cin>>n;
	int j=1,k=n,t=n;
	for(int i=1;i<=n,j<=k;i++){
		if(i%2!=0){
			a[j]=i;
			b[j]=i;
			j++;
		}else{
			a[k]=i;
			b[k]=i;
			k--;
		}
	}
	while(n){
		for(int i=1;i

大的数尽量往中间放(因为他们能被加更多次),小的数往两边放!

D 阿宁的毒瘤题

通过率:867/3977

F 阿宁的二进制

通过率:1242/4361

时间不够,未通过。。。。

思路:操作数不多 在线回答 优先队列!!!

注意加深对优先队列的理解!!!

解法一:(最简解法)

思路:每输入一个a[i]都进行a[i]=f(a[i]),直到a[i]=1进行f(a[i])值不变为止,用数组b记录每次f(x)后的结果,最后对数组b进行排序,进行几次操作即输出第几大的值

#include
#include
#include
#define int long long 
using namespace std;

const int N=200005;
int a[N],b[1000000];
signed main(){
	int n,q,t=0;
	cin>>n>>q;
	for(int i=0;i>a[i];
		while(a[i]>1){
			t++;
			b[t]=a[i];
			a[i]=__builtin_popcount(a[i]);	
		}
	}
	sort(b+1,b+1+t);
	while(q){
		int k;
		cin>>k;
		if(k>=t){
			cout<<1<<'\n';;
		}else{
			cout<

解法二:(优先队列)  

关于优先队列,传送门:c++优先队列(priority_queue)用法详解_吕白_的博客

关键: 头文件 #include

            定义 priority_queue q    

            插入 push

            弹出 pop

            访问队头元素 top

            队列是否为空 empty

            返回队列内元素个数 size

            原地构造一个元素并插入队列 emplace

            交换内容 swap

#include
#include
#include
#define int long long 
using namespace std; 

const int N=1000005;
int ans[N];
signed main(){
	int n,q;
	cin>>n>>q;
	priority_queue qp;
	for(int i=0;i>a;
		qp.push(a);                   
	}
	for(int i=1;i<=N;i++){
		int x=__builtin_popcount(qp.top());
		qp.pop();
		qp.push(x);
		ans[i]=qp.top();
	}
	for(int i=0;i>x;
		cout<

G 阿宁的整数配对(简单题)

通过率:2197/5610

睡醒之后还剩一个多小时,这道题思虑很清楚,一发入魂!

我的思路:先对数组排序,然后计算数组两端每端两个数的乘积,每次答案加上最大的一个值,直到取到所给的对数为止

赛场AC代码:

#include
#include
#include
#define int long long
using namespace std;

const int N=200005;
int a[N];
signed main(){
	int n,k;
	cin>>n>>k;
	for(int i=0;i>a[i];
	}
	sort(a,a+n);
	int ans=0,i=0,j=n-1;
	while(k--){
		int x,y;
		x=a[i]*a[i+1];
		y=a[j]*a[j-1]; 
		if(x>=y){
			ans+=x;
			i+=2;
		}else{
			ans+=y;
			j-=2;
		}
	}
	cout<

H 阿宁讨伐虚空(简单题)

通过率:2653/7202

赛场上未AC,WA了十发,最后心态崩了睡觉去了。。。。

因为代码里有一点小错误,始终都没有发现(把概率1.0当成了100.0).。。。。

修改后AC 代码:

#include
#include
#define int long long
using namespace std;

signed main(){
	double x;
	double l,r;
	cin>>x;
	cin>>l>>r;
	if(x<=l){
		cout<<"0.00000000";
		return 0;
	}
	if(x>r){
		cout<<"1.00000000";
		return 0;
	}
	double ans;
	ans=(x-l)/(r-l+1);
	printf("%.8lf",ans);
	
	return 0;
} 

注意double和long double的区别和含义,f和lf的区别和含义!!!

最简单的写法:

#include
#include
#define int long long
using namespace std;

signed main(){
	double x,l,r;
    cin>>x>>l>>r;
    cout<

I 阿宁前往沙城 

通过率:460/1950

思路:使用不定长数组g[i]来存储节点i所连接的节点,num[i]来存储节点1和节点i之间的路径长度,len[i]记录到达节点i经历的路径长度,vis[i]记录i点是否被访问过

#include
#include
#include
#include
#define int long long
using namespace std;

const int N=200005;
vector g[N];//存储节点所连接的节点
queue q;
int num[N];//存储节点1和节点之间的路径长度
int len[N];//记录到达节点i经历的路径长度
bool vis[N];//记录节点是否被访问
int n,m;

void bfs(){
	int t=q.front();//取队列的第一个元素 
	q.pop();//删除队列的第一个元素 
	//防止第一个节点为1 
	if(t==n){
		return;
	}	
	//列举每一个节点所连接的节点 
	for(int i=0;i>n>>m;
	for(int i=0;i>u>>v>>w;
		g[u].push_back(v);
		g[v].push_back(u);
		//若遇到节点1则使用数组num来记录节点与1之间的路径长度 
		if(u==1){
			num[v]=w;
		}  
		if(v==1){
			num[u]=w;
		}
	}
	q.push(1);
	vis[1]=1;
	bfs();
	if(len[n]==m){
		cout<

你可能感兴趣的:(算法,c++,c语言,数据结构,蓝桥杯)