七夕学算法

目录

P1031 [NOIP2002 提高组] 均分纸牌

原题链接 :

题面 : 

 思路 :

代码 : 

P1036 [NOIP2002 普及组] 选数

原题链接 :

题面 : 

思路 :

代码 : 

P1060 [NOIP2006 普及组] 开心的金明

原题链接 : 

题面 : 

 思路 : 

01背包例题 :

代码 :  

P1100 高低位交换

原题链接 : 

题面 : 

 思路 :

代码 : 

P1097 [NOIP2007 提高组] 统计数字

原题链接 

题面 : 

 ​编辑

思路 : 

代码 1: map + set

 代码 2  : 数组排序


视频链接 : Erik_Tse

P1031 [NOIP2002 提高组] 均分纸牌

原题链接 :

         均分纸牌

题面 : 

 思路 :

  根据贪心的思想,肯定是先将第一堆的纸牌弄成n张,再去弄后面的!

循环往后,如果当前队中牌数小于n,从下一堆中移差值牌数过来,

如果大于的话,就将差值牌数移给下一堆。最后一定就是满足题目要求的!!!

所以请看代码 : 

代码 : 

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 102;
int n,a[N];
LL ans,sum,avg,k;
int main() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
	avg = sum / n;
	for(int i=1;i<=n;i++){
		if(a[i] < avg){
			k = avg - a[i];
			a[i] += k;
			a[i+1] -= k;
			ans ++;
		}
		if(a[i] > avg){
			k = a[i] - avg;
			a[i] -= k;
			a[i+1] += k;
			ans ++; 
		}
	}
	cout<<ans<<endl;
	return 0;
}

P1036 [NOIP2002 普及组] 选数

原题链接 :

 选数

题面 : 

思路 :

就是一个dfs找子集的问题,没什么好说的,详细请看代码 !!!

实现组合型枚举例题 : 实现组合型枚举

代码 : 

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 22;
int n,a[N],k;

bool is_prime(int x){//判断素数模板,要记住 
	if(x < 2) return false;
	for(int i=2;i<=x/i;i++) if(x%i == 0) return false;
	return true;
}

LL dfs(int dep,int cnt,int sum){ 
	if(cnt == k) return (int)is_prime(sum);//找到k个元素
	if(dep > n) return 0;//搜索到数组最后一个元素,退出
	// 子集问题,选或不选 两个分支 :  
	// 选 : dfs(dep+1,cnt,sum) 
	// 不选 : dfs(dep + 1,cnt + 1 , sum + a[dep])
	LL res = 0;
	res += dfs(dep + 1 , cnt , sum);
	res += dfs(dep + 1 , cnt + 1 , sum + a[dep]); 
	return res;
}

int main() {
	cin >> n >> k;
	for(int i=1;i<=n;i++) cin>>a[i];
	// dfs(dep,cnt,sum)
	// dep : 下标 
	// cnt : 当前选了几个数 
	// sum : 当前选数之和  
	cout << dfs(1,0,0) << endl;
	
	return 0;
}

P1060 [NOIP2006 普及组] 开心的金明

原题链接 : 

开心的金明

题面 : 

 思路 : 

本质上就是一个01背包问题,分选和不选两种情况!!!不懂得可以看01背包例题 : 

01背包例题 :

 2. 01背包问题 - AcWing题库

代码 :  

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 3e4+10;
int n , m;
int v[27],w[27];
LL dp[30][N];//表示从前i个物品中选,重前不过j的最大价值 

int main() {
	cin >> n >> m;
	for(int i=1;i<=m;i++) cin >> v[i] >> w[i];
	// 本质 : 01背包 
	for(int i=1;i<=m;i++){
		for(int j=0;j<=n;j++){
			if(j < v[i]) dp[i][j] = dp[i-1][j];
			else dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + v[i]*w[i]);
		}
	}
	cout<<dp[m][n]<<endl;
	return 0;
}

P1100 高低位交换

原题链接 : 

高低位交换 - 洛谷

题面 : 

 思路 :

位运算,模拟即可

代码 : 

#include<iostream>
using namespace std;
typedef long long LL;
LL x,ans,st,en;
int main()
{
    scanf("%lld",&x);
	st = x >> 16;
	en = x % (65536);
	en = (en << 16);
	ans = en + st;
	printf("%lld",ans); 
	return 0;
}

P1097 [NOIP2007 提高组] 统计数字

原题链接 

统计数字

题面 : 

 

思路 : 

用map+set : 

代码 1: map + set

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <set>
using namespace std;
typedef long long LL;
const int N = 3e4+10;
int m,x;
unordered_map<int,int> mp;
set<int> st;

int main() {
	cin >> m;
	while(m--){
		cin>>x;
		mp[x]++;
		st.insert(x);
	}
	for(auto it = st.begin() ; it != st.end() ; it ++){
		cout << *it << " " << mp[*it] << endl;
	}
	return 0;
}

 代码 2  : 数组排序

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <set>
using namespace std;
typedef long long LL;
const int N = 2e5+10;
int n, a[N], cnt;

int main() {
	cin >> n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
		cnt ++;
		if(i==n || a[i]!=a[i+1]){
			cout<<a[i] <<" "<<cnt<<endl;
			cnt = 0;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ros275229/article/details/132461152