目录
[P1031 [NOIP2002 提高组] 均分纸牌](#P1031 [NOIP2002 提高组] 均分纸牌)
[原题链接 :](#原题链接 :)
[题面 :](#题面 :)
[思路 :](#思路 :)
[代码 :](#代码 :)
[P1036 [NOIP2002 普及组] 选数](#P1036 [NOIP2002 普及组] 选数)
[原题链接 :](#原题链接 :)
[题面 :](#题面 :)
[思路 :](#思路 :)
[代码 :](#代码 :)
[P1060 [NOIP2006 普及组] 开心的金明](#P1060 [NOIP2006 普及组] 开心的金明)
[原题链接 :](#原题链接 :)
[题面 :](#题面 :)
[思路 :](#思路 :)
[01背包例题 :](#01背包例题 :)
[代码 :](#代码 :)
[P1100 高低位交换](#P1100 高低位交换)
[原题链接 :](#原题链接 :)
[题面 :](#题面 :)
[思路 :](#思路 :)
[代码 :](#代码 :)
[P1097 [NOIP2007 提高组] 统计数字](#P1097 [NOIP2007 提高组] 统计数字)
[题面 :](#题面 :)
[思路 :](#思路 :)
[代码 1: map + set](#代码 1: map + set)
[代码 2 : 数组排序](#代码 2 : 数组排序)
视频链接 : Erik_Tse
P1031 [NOIP2002 提高组] 均分纸牌
原题链接 :
题面 :
思路 :
根据贪心的思想,肯定是先将第一堆的纸牌弄成n张,再去弄后面的!
循环往后,如果当前队中牌数小于n,从下一堆中移差值牌数过来,
如果大于的话,就将差值牌数移给下一堆。最后一定就是满足题目要求的!!!
所以请看代码 :
代码 :
cpp
#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找子集的问题,没什么好说的,详细请看代码 !!!
实现组合型枚举例题 : 实现组合型枚举
代码 :
cpp
#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背包例题 :
代码 :
cpp
#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 高低位交换
原题链接 :
题面 :
思路 :
位运算,模拟即可
代码 :
cpp
#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
cpp
#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 : 数组排序
cpp
#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;
}