南邮
1.求一堆输入的最值

先开一个动态数组,然后输入,排序,取arr数组的头和尾。
cpp
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int n;
while(cin>>n){
vector<int> arr(n);
for(int i =0 ;i<n;i++){
cin>>arr[i];
}
sort(arr.begin(),arr.end());
cout<<arr[n-1]<<" "<<arr[0]<<endl;
}
}
2.素数+回文数

cpp
#include<iostream>
using namespace std;
bool isPrime(long long x){//素数:只能1和他本身作为因子
if(x<=1) return false;
if(x == 2)return true;
if(x%2==0)return false;//奇偶数加速,后面只判断奇数
for(long long i = 3;i*i<=x;i++){
if(x%i == 0)return false;
}
return true;
}
bool isPalindrome(long long x){//判断回文数
long long ori = x,rev = 0;
while(x>0){
rev = rev * 10 + x % 10;
x /=10;
}
if(ori == rev) return true;
else return false;
}
int main(){
int n;
cin>>n;
for(int i = 0;i<n;i++){
long long a;
cin>>a;
if(a<99999 && isPrime(a) && isPalindrome(a))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
字符串判断回文数
cpp
bool isPalindrome(long long x){
string s = to_string(x);
int l = 0, r = s.size()-1;
while(l < r){
if(s[l] != s[r]) return false;
l++; r--;
}
return true;
}
3.十进制转任意进制


cpp
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
char getChar(int x){
if(x<10)return '0'+x;
else return 'A'+(x-10);
}
string convert(int N,int R){
string res;
bool neg = false;
if(N<0){
neg = true;
N = -N;
}
if(N == 0){
return "0";
}
while(N>0){
int rem = N % R;
res += getChar(rem);
N = N/R;
}
reverse(res.begin(),res.end());
if(neg) res = "-"+res;
return res;
}
int main(){
int T;
cin>>T;
while(T--){
int N,R;
cin>>N>>R;
cout<<convert(N,R)<<endl;
}
return 0;
}
也可以用map存映射关系
cpp
#include<unordered_map>
unordered_map<int, char> mp = {
{0, '0'}, {1, '1'}, {2, '2'}, {3, '3'}, {4, '4'},
{5, '5'}, {6, '6'}, {7, '7'}, {8, '8'}, {9, '9'},
{10, 'A'}, {11, 'B'}, {12, 'C'}, {13, 'D'}, {14, 'E'}, {15, 'F'}
};
char getChar(int x){
return mp[x];
}
4.涂色问题

先看每一列:
有两种方案,aba和abc
aba:第一个格子3种颜色可选,第二个格子2种,第三个格子跟第一个一样:3×2 = 6
abc:第一个格子3种颜色可选,第二个格子2种,第三个格子1种:3×2×1 = 6
然后假设第 i-1 列确定了,看第 i 列有几种方案:

得到:
cpp
a[i]=2*a[i-1]+2*b[i-1]
b[i]=2*a[i-1]+3*b[i-1]
当前状态的可能性,与上一列是aba还是abc相关

cpp
#include<iostream>
using namespace std;
const long long MOD = 1e9+7;
int main(){
int n;
cin>>n;
long long a[n],b[n];
a[0]=6;
b[0]=6;
for(int i = 1;i<n;i++){
a[i] = (2*a[i-1]+2*b[i-1])%MOD;
b[i] = (2*a[i-1]+3*b[i-1])%MOD;
}
cout<<(a[n-1]+b[n-1])%MOD<<endl;
return 0;
}
可以优化,把数组空间去掉
cpp
#include<iostream>
using namespace std;
const long long MOD = 1e9+7;
int main(){
int n;
cin>>n;
long long a = 6;
long long b = 6;
for(int i = 1;i<n;i++){
long long na = (2*a + 2*b)%MOD;
long long nb = (2*a + 3*b)%MOD;
a = na;
b = nb;
}
cout<<(a+b)%MOD<<endl;
return 0;
}
5.最大公约数和最小公倍数

求最大公约数gcd:




最小公倍数lcm:

cpp
#include<iostream>
using namespace std;
int gcd(int a,int b){
while(b!=0){
int t = a%b;
a = b;
b = t;
}
return a;
}
int main(){
int A,B;
cin>>A>>B;
int g = gcd(A,B);
int l = A/g * B;//防止溢出
cout<<g<<" "<<l<<endl;
return 0;
}
6.斐波那契数列

cpp
#include<iostream>
using namespace std;
int Fibonacci(int n){
if(n==0)return 0;
if(n==1 || n==2)return 1;
return Fibonacci(n-1) + Fibonacci(n-2);
}
int main(){
int n;
cin>>n;
cout<<Fibonacci(n);
return 0;
}
7.回文数

cpp
#include<iostream>
#include<string>
using namespace std;
bool isPalindrome(string s){
int l =0;
int r = s.size() - 1;
while(l<r){
if(s[l] != s[r] &&s[l]-32 != s[r]&&s[l] != s[r]-32){//不区分大小写
return false;
}
l++;
r--;
}
return true;
}
int main(){
string s;
cin>>s;
if(isPalindrome(s))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
8.级数求和

注意用double类型,除法的时候写1.0
cpp
#include<iostream>
using namespace std;
int main(){
int k;
cin>>k;
long long n = 1;
double sn = 0;
while(k>sn){
sn+=(1.0/n);
if(sn > k) break;
n++;
}
cout<<n;
}
9.可乐瓶换可乐

cpp
#include<iostream>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
long long total = n;
long long empty = n;
while(empty >= k){
long long get = empty/k;
long long rem = empty%k;
total += get;
empty = get + rem;
}
cout<<total<<endl;
return 0 ;
}
定义get和rem,然后循环
10.周天子分封(sort排序)

这个题目就是我刚开始用的 int arrn;
然后后面使用sort排序 ,sort(arr.begin(),arr.end());
报错了,原来是原生数组要传首地址、尾后地址(原生数组没有.begin .end方法):
sort(arr , arr + n);
而且int arrn不是标准cpp写法,最好写成int arr1005或者使用vector
还有就是输入的地方我写的有点简陋,但是不知道怎么写的优雅一点:
cpp
for(int i = 0;i<n;i++){
int p;
cin>>p;
arr[i] = p;
}
问问豆包:
cpp
for(int i = 0;i<n;i++){
cin>>arr[i];
}
cpp
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n;
cin>>n;
int arr[1005];
for(int i = 0;i<n;i++){
int p;
cin>>p;
arr[i] = p;
}
sort(arr,arr + n);
cout<<arr[n-1]+arr[n-2]+arr[n-3];
}
10.矩阵变换(把某行列改为0)

这个题用vector创建二维数组
二维 vector 本质:vector< vector<int> >,外层是行,内层是每一行的一维 vector
cpp
// n行 m列,默认值 0
vector<vector<int>> arr(n, vector<int>(m));
然后这个题的坑:
不能记录完,然后遍历数组,看看谁是1,然后再循环把这个数的纵横两条线的数字置零。
因为有可能这条线上有1,代表这边也需要把纵横置零,没提前记录就把它改了,就找不到了
应该先设置2个bool数组,记录col和row,如果输入的数字是1,那就把这行和这列设置为true,
后续改数字的时候,就看如果col是true or row是true,就置零。
cpp
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> arr(n,vector<int>(m));
vector<bool> row(n);
vector<bool> col(m);
for(int i = 0;i<n;i++){
for(int j =0 ;j<m;j++){
cin>>arr[i][j];
if(arr[i][j] == 1){
row[i] = true;
col[j] = true;
}
}
}
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(row[i] || col[j]){
arr[i][j] = 0;
}
}
}
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
11.公路上的树,修路占用

这个题要注意开辟的数组的大小,因为树是从数轴的0开始栽,到 L 一共L+1棵树
cpp
#include<iostream>
#include<vector>
using namespace std;
int main(){
int l,m;
cin>>l>>m;
vector<bool> arr(l+1,true);
for(int i = 0;i<m;i++){
int u,v;
cin>>u>>v;
for(int j = u;j<=v;j++){
if(arr[j]){
arr[j] = false;
}
}
}
int count = 0;
for(int i = 0;i<=l;i++){
if(arr[i]){
count++;
}
}
cout<<count;
return 0;
}
12.算分环节
这道题用到了accumulate,保留两位小数输出
cpp
#include<iostream>
#include<vector>
#include<numeric>
#include<algorithm>
#include<iomanip>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> arr(n,vector<int>(m));
vector<double> avgs(n);
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
cin>>arr[i][j];
}
}
for(int i = 0;i<n;i++){
sort(arr[i].begin(),arr[i].end());
int sum = accumulate(arr[i].begin(), arr[i].end(), 0);
double avg = (sum - arr[i].front() - arr[i].back())*1.0 / (m-2);
avgs[i] = avg;
}
sort(avgs.begin(),avgs.end());
cout<<fixed<<setprecision(2)<<avgs.back()<<endl;
}
13.输入年和天,输出几月几日

cpp
#include<iostream>
using namespace std;
bool isRunNian(int y){
if(y % 100 == 0){
if(y % 400 == 0){
return true;
}
return false;
}
else if(y % 4 == 0){
return true;
}
return false;
}
int main(){
int Y,n;
cin>>Y>>n;
int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31,30,31};
if(isRunNian(Y)){
days[2] = 29;
}
int month = 1;
while(n>days[month]){
n-=days[month];
month++;
}
cout<<month<<" "<<n;
return 0;
}
14.子串统计(kmp算法)

cpp
#include<iostream>
#include<vector>
#define FAST ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
using namespace std;
vector<int> getNext(string &q){
int m = q.size();
vector<int> next(m,0);
for(int i = 1,j = 0;i<m;i++){
while(j>0 && q[i] != q[j]){
j = next[j-1];
}
if(q[i] == q[j]){
j++;
}
next[i] = j;
}
return next;
}
int kmp(string &s,string &q,vector<int> &next){
int ans = 0;
for(int i = 0,j = 0;i<s.size();i++){
while(j>0 && s[i] != q[j]){
j = next[j-1];
}
if(s[i] == q[j]){
j++;
}
if(j == q.size()){
ans++;
j = next[j-1];
}
}
return ans;
}
int main(){
FAST;
int n;
cin>>n;
while(n--){
string s,q;
cin>>s>>q;
vector<int> next = getNext(q);
int ans = kmp(s,q,next);
cout<<ans<<endl;
}
return 0;
}
关闭同步 + 解绑,cin 速度几乎追上scanf,时间够用直接通过。
没写这句的时候没有通过:
#define FAST ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
15.社交网络

这个题刚开始想用vector开二维数组,然后输入的用户代码id当做数组下标,结果发现开的数组是arrn,但是id能达到10^9,

段错误,发生越界
得用哈希map,键存id,值是一个vector数组,添加对应的好友
cpp
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
int main(){
int n;
cin>>n;
unordered_map<int,vector<int>> map;
for(int i = 0;i<n;i++){
int a,b;
cin>>a>>b;
map[a].push_back(b);
map[b].push_back(a);
}
int max = 0;
for(auto &p : map){
if(p.second.size() > max){
max = p.second.size();
}
}
cout<<max;
return 0;
}
