数学
质素判断
#include<iostream>
using namespace std;
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;
}
int main(){
int n;
cin>>n;
while(n--){
int x;
cin>>x;
if(is_prime(x)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
return 0;
}
质素筛
#include<iostream>
using namespace std;
const int N=1000010;
int st[N]; //标记是否筛过
int prime[N]; //质素数组
int cnt;
void get_prime(int n){
for(int i=2;i<=n;i++){
if(!st[i])prime[cnt++]=i; //i是数组,则加入质素数组
for(int j=i;j<=n;j+=i){ //i的倍数不是质素,应该筛掉
st[j]=true;
}
}
}
int main(){
int n;
cin>>n;
get_prime(n);
//输出
// for(int i=0;i<cnt;i++){
// cout<<prime[i]<<' ';
// }
cout<<cnt<<endl;
return 0;
}
四舍五入
- 取整:(int)(浮点数+0.5)
#include<iostream>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
double c=n*1.0/m; //注意是浮点数除法
cout<<(int)(c+0.5)<<endl;
return 0;
}
- 保留3位小数 (int)(x*1000+0.5)/1000.0
#include<iostream>
using namespace std;
int main(){
double n=3.1415;
cout<<(int)(n*1000+0.5)/1000.0<<endl;
return 0;
}
- 使用库函数
#include<iostream>
#include<cmath>
using namespace std;
int main(){
double n=3.1415;
cout<<round(n*1000)/1000; //保留三位小数
return 0;
}
分解质因数
#include<iostream>
using namespace std;
int main(){
int n;cin>>n;
for(int i=2;n>1;i++){
while(n%i==0){
printf("%d",i);
n/=i;
if(n==1)cout<<endl; //分解完毕
else cout<<' ';
}
}
return 0;
}
回文素数
输出n~m之间的回文素数
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int primes[10000000];
bool st[10000000];
int cnt;
bool is_hui(int n){
int m=n;
int sum=0;
for(int i=n;i>0;i/=10){
sum=10*sum+i%10;
}
if(m==sum){
return true;
}else{
return false;
}
}
void get_primes(int n){
for(int i=2;i<=n;i++){
if(!st[i])primes[cnt++]=i;
for(int j=i;j<=n;j+=i){
st[j]=true;
}
}
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
get_primes(m);
for(int i=0;i<cnt;i++){
if(is_hui(primes[i]) && primes[i]>=n){
cout<<primes[i]<<endl;
}
}
return 0;
}
高精度加法
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int a[110],b[110],c[110];
int main(){
string str1,str2;
cin>>str1>>str2;
for(int i=0;i<str1.size();i++){
a[str1.size()-1-i]=str1[i]-'0';
}
for(int j=0;j<str2.size();j++){
b[str2.size()-1-j]=str2[j]-'0';
}
int len=max(str1.size(),str2.size());
for(int i=0;i<len;i++){
c[i]=c[i]+a[i]+b[i];
c[i+1]=c[i]/10;
c[i]%=10;
}
len+=1;
if(c[len-1]==0 && len>1){ //检验最高位是否为零
len-=1;
}
for(int i=0;i<len;i++){
cout<<c[len-1-i]; //逆序输出
}
return 0;
}
高精度减法
#include<bits/stdc++.h>
using namespace std;
int a[110],b[110],c[110];
int flag=0;
int main(){
string str1,str2;
cin>>str1>>str2;
if(atoi(str1.c_str())<atoi(str2.c_str()) && str1.size()==str2.size() || str1.size()<str2.size()){
swap(str1,str2);
flag=1;
}
for(int i=0;i<str1.size();i++){
a[str1.size()-1-i]=str1[i]-'0';
}
for(int i=0;i<str2.size();i++){
b[str2.size()-i-1]=str2[i]-'0';
}
int len=max(str1.size(),str2.size());
for(int i=0;i<len;i++){
if(a[i]<b[i]){
a[i+1]-=1;
a[i]+=10;
}c[i]=a[i]-b[i];
}
while(c[len-1]==0 && len>1){ //取出前导零
len-=1;
}
if(flag){
cout<<'-';
}
for(int i=0;i<len;i++){
cout<<c[len-1-i];
}
return 0;
}
任意进制转10进制
int to_10(string s,int b){ //将b进制的s转化为10进制
int num=0;
for(int i=0;i<s.size();i++){
num=num*b+s[i]-'0';
}
return num;
}
数组
数组平移
将a数组中第一个元素移到数组末尾,其余数据依次往前平移一个位置。
#include<iostream>
using namespace std;
int main(){
int n;cin>>n;
int q[1000];
for(int i=0;i<n;i++){
cin>>q[i];
}
int temp=q[0]; //保存头部元素
for(int i=0;i<n;i++){ //数组全部从后往前赋值
q[i]=q[i+1];
}
q[n-1]=temp; //尾部元素单独再赋值一遍
for(int i=0;i<n;i++){
cout<<q[i]<<' ';
}
return 0;
}
从大到小 排序
将10个数从大到小排序
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b){
return a>b; //从大到小
}
int main(){
int q[10];
for(int i=0;i<10;i++){
cin>>q[i];
}
sort(q,q+10,cmp);
for(int i=0;i<10;i++){
cout<<q[i]<<' ';
}
return 0;
}
杨辉三角
打印杨辉三角前10行
#include<iostream>
using namespace std;
int q[11][11];
int main(){
for(int i=1;i<=10;i++){
q[i][1]=1,q[i][i]=1;
for(int j=2;j<i;j++){ //第二列~倒数第二列
q[i][j]=q[i-1][j]+q[i-1][j-1];
}
}
for(int i=1;i<=10;i++){
for(int k=1;k<=10-i;k++){
cout<<" ";
}
for(int j=1;j<=i;j++){
printf("%6d",q[i][j]); //格式输出
}
cout<<endl;
}
return 0;
}
回文数的判断
输入一串字符,字符个数不超过100,且以“.”结束。判断它们是否构成回文。“Yes”/“No”
#include<iostream>
#include<cstring>
using namespace std;
char s[1000];
char s2[1000];
bool is_huiwen(char s[]){
for(int i=0,j=strlen(s)-1;i<j;i++,j--){
if(s[i]!=s[j]){
return false;
}
}
return true;
}
int main(){
cin>>s;
int j=0;
for(int i=0;i<strlen(s)-1;i++){
s2[j++]=s[i];
}
if(is_huiwen(s2)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
return 0;
}
约瑟夫环
N个人围成一圈,从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M的人出圈;……输出依次出圈的人的编号。N,M由键盘输入。
使用指针p循环遍历,每次当遍历到m时,标记为出局,并输出编号
#include<iostream>
using namespace std;
bool isOut[100];
int n,m,p; //p指向当前遍历到的位置
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){ //一共输出n次
for(int j=0;j<m-1;j++){ //循环m-1次,p指向m的前一个位置
while(isOut[p]==true){
p=(p+1)%n; //已经出局就跳过
}
p=(p+1)%n; //p往后遍历
}
//退出内层for循环后,p指向m
while(isOut[p]==true){
p=(p+1)%n;
}
isOut[p]=true;
cout<<" "<<p+1; //下标从0开始,打印出局的人编号
}
return 0;
}
矩阵对角线操作
已知一个6*6的矩阵(方阵),把矩阵二条对角线上的元素加上10,然后输出这个新矩阵。输出得到的新矩阵,注意每个元素占5个长度。
#include<iostream>
using namespace std;
int main(){
int q[7][7]; //从下标1开始存,则开数组要多开一维
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++){
cin>>q[i][j];
}
}
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++){
if(i==j){ //副对角线
q[i][j]+=10;
}
if(i+j==7&&i!=j){ //主对角线
q[i][j]+=10;
}
}
}
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++){
printf("%5d",q[i][j]);
}
cout<<endl;
}
return 0;
}
行列式转换
输入一个3*3的矩阵,将矩阵的行列转换。
#include<iostream>
using namespace std;
int main(){
int q[4][4],temp[4][4];
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
cin>>q[i][j];
temp[j][i]=q[i][j]; //边读取边转换
}
}
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
cout<<temp[i][j]<<' ';
}
cout<<endl;
}
return 0;
}
蛇形填数
在nn的方阵里填入1,2,3,···,nn,要求填成蛇形。例如n=4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上述的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n<=8. 具体格式看下面的样例输出。
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
const int N=9;
int a[N][N];
int main(){
int n;cin>>n;
int loop=ceil((double)n/2); //向上取整,填充的圈数
int cnt=1;
for(int i=1;i<=loop;i++){
//右上到右下
for(int x=i,y=n-i+1;x<=n-i+1;x++){
a[x][y]=cnt++;
}
//右下到左下
for(int x=n-i+1,y=n-i;y>=i;y--){
a[x][y]=cnt++;
}
//左下到左上
for(int x=n-i,y=i;x>=i;x--){
a[x][y]=cnt++;
}
//左上到右上
for(int x=i,y=i+1;y<=n-i;y++){
a[x][y]=cnt++;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<setw(3)<<a[i][j];
}
cout<<endl;
}
return 0;
}
数组去重
给定含有n个整数的序列,要求对这个序列进行去重操作。所谓去重,是指对这个序列中每个重复出现的数,只保留该数第一次出现的位置,删除其余位置。
#include<iostream>
using namespace std;
int map[20000],m=0;
int main(){
int n;cin>>n;
int nums[20000],temp[20000];
for(int i=0;i<n;i++){
cin>>nums[i];
map[nums[i]]++;
if(map[nums[i]]==1){
temp[m++]=nums[i];
}
}
for(int i=0;i<m;i++){
cout<<temp[i]<<' ';
}
return 0;
}
区间计数-校门外的树
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
#include<iostream>
using namespace std;
bool has_tree[10000]; //标记是否有树
int main(){
int len,num;
cin>>len>>num;
for(int i=0;i<=len;i++){
has_tree[i]=true; //初始化每个位置都有树
}
for(int i=0;i<num;i++){
int start,end;
cin>>start>>end;
for(int j=start;j<=end;j++){
has_tree[j]=false; //该位置移除树
}
}
int cnt=0;
for(int i=0;i<=len;i++){
if(has_tree[i]==true){
cnt++;
}
}
cout<<cnt<<endl;
return 0;
}
开关灯
假设有N盏灯(N为不大于5000的正整数),从1到N按顺序依次编号,初始时全部处于开启状态;有M个人(M为不大于N的正整数)也从1到M依次编号。
第一个人(1号)将灯全部关闭,第二个人(2号)将编号为2的倍数的灯打开,第三个人(3号)将编号为3的倍数的灯做相反处理(即将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以后的人都和3号一样,将凡是自己编号倍数的灯做相反处理。
请问:当第M个人操作之后,哪几盏灯是关闭的,按从小到大输出其编号,其间用逗号间隔。
#include<iostream>
#include<cstring>
using namespace std;
int a[5000]; //1表示关闭,0表示开启
int main(){
int n,m;
cin>>n>>m;
memset(a,0,sizeof a);
for(int i=1;i<=m;i++){ //遍历每个人
for(int j=1;j<=n;j++){ //遍历每盏灯
if(j%i==0)a[j]=!a[j]; //a[j]初始为0,第一轮循环a[1~n]全为1,用1表示关闭
}
}
for(int j=1;j<=n;j++){
if(a[j]){ //1表示关闭
if(j==1)cout<<j;
if(j!=1)cout<<","<<j;
}
}
return 0;
}
铺地毯
一共有n 张地毯,编号从1 到n。现在将这些地毯按照
编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。
#include<iostream>
using namespace std;
int x0[1000],y0[1000],len[1000],wid[1000];
int main(){
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>x0[i]>>y0[i]>>len[i]>>wid[i]; //左下角下标和长宽
}
int x,y;
cin>>x>>y;
for(int i=n;i>=1;i--){ //倒着判断
if(x>=x0[i]&&x<=(x0[i]+len[i])&&y>=y0[i]&&y<=(y0[i]+wid[i])){
cout<<i<<endl;
return 0;
}
}
cout<<"-1"<<endl;
}
计算鞍点
给定一个5*5的矩阵,每行只有一个最大值,每列只有一个最小值,寻找这个矩阵的鞍点。
鞍点指的是矩阵中的一个元素,它是所在行的最大值,并且是所在列的最小值。
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
int matrix[5][5],max_row[5],min_col[5];
int main(){
for(int i=0;i<5;i++){
min_col[i]=INF; //注意最小值要初始化为大数
}
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
cin>>matrix[i][j];
}
}
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
max_row[i]=max(max_row[i],matrix[i][j]);
}
}
for(int j=0;j<5;j++){
for(int i=0;i<5;i++){
min_col[j]=min(min_col[j],matrix[i][j]);
}
}
bool found=false;
int point=0,x=0,y=0;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(matrix[i][j]==max_row[i] && matrix[i][j]==min_col[j]){
point=matrix[i][j];
x=i,y=j;
found=true;
break;
}
}
}
if(found){
cout<<x+1<<' '<<y+1<<' '<<point<<endl;
}else{
cout<<"not found"<<endl;
}
return 0;
}
矩阵乘法
计算两个矩阵的乘法。n×m阶的矩阵A乘以m×k阶的矩阵B得到的矩阵C 是n×k阶的C矩阵,输入第一行为n, m,
k,表示A矩阵是n行m列,B矩阵是m行k列,n, m, k均小于100。 然后先后输入A和B两个矩阵,A矩阵n行m列,B矩阵m行k列
#include<iostream>
using namespace std;
const int N=105;
int A[N][N],B[N][N],C[N][N];
int n,m,k;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>A[i][j];
}
}
for(int i=1;i<=m;i++){
for(int j=1;j<=k;j++){
cin>>B[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
for(int k=1;k<=m;k++){
C[i][j]+=A[i][k]*B[k][j];
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
cout<<C[i][j]<<' ';
}
cout<<endl;
}
return 0;
}
字符串
取出多余的空格
- 利用scanf循环读取,跳过空格,读一个打印一个
#include<iostream>
using namespace std;
int main(){
char s[200];
while(scanf("%s",&s)==1){
printf("%s ",s);
}
return 0;
}
- 设置空格标记,遇到连续空格暂停复制
#include<iostream>
#include<cstring>
using namespace std;
char str[200],temp[200];
int start,cnt_blank;
int main(){
cin.getline(str,200);
for(int i=0;i<=strlen(str);i++){
if(str[i]==' '){
cnt_blank++;
if(cnt_blank==1){
temp[start++]=str[i];
}
}else{
cnt_blank=0;
temp[start++]=str[i];
}
}
cout<<temp;
return 0;
}
字符串移位包含
对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾形成新的字符串。
给定两个字符串s1和s2,要求判定其中一个字符串是否是另一个字符串通过若干次循环移位后的新字符串的子串。例如CDAA是由AABCD两次移位后产生的新串BCDAA的子串,而ABCD与ACBD则不能通过多次移位来得到其中一个字符串是新串的子串。
#include<bits/stdc++.h>
using namespace std;
int main(){
char s1[40];
char s2[40];
char s3[40]; //用于连接a
char tp[50]; //用于交换
cin>>s1>>s2;
if(strlen(s1)<strlen(s2)){
strcpy(tp,s1);
strcpy(s1,s2);
strcpy(s2,tp);
}
strcpy(s3,s1);
if(strstr(strcat(s1,s3),s2)==NULL)cout<<"false";
else cout<<"true";
return 0;
}
打印输出
输入n个数,要求程序按输入时的逆序把这n个数打印出来,已知整数不超过100个。也就是说,按输入相反顺序打印这n个数。
#include<iostream>
#include<cstring>
using namespace std;
int main(){
char a[100];
cin.getline(a,100); //读取一整行,逆序输出
int len_a=strlen(a);
for(int i=len_a-1;i>=0;i--){
cout<<a[i]; //不用加空格
}
return 0;
}
字符串判等
判断两个由大小写字母和空格组成的字符串在忽略大小写,且忽略空格后是否相等。
#include<iostream>
#include<cstring>
using namespace std;
bool check_equal(char a[],char b[]){
int lena=strlen(a),lenb=strlen(b);
if(lena!=lenb){
return false;
}
for(int i=0;i<lena;i++){
if(a[i]!=b[i]){
return false;
}
}
return true;
}
char str1[100],str2[100];
char temp1[100],temp2[100];
int main(){
cin.getline(str1,100);
cin.getline(str2,100);
int m=0,n=0;
for(int i=0;i<strlen(str1);i++){
if(str1[i]!=' '){
if(str1[i]>='a' && str1[i]<='z'){
temp1[m++]=str1[i];
}else{
temp1[m++]=str1[i]+32; //大小写字母相差32
}
}
}
for(int i=0;i<strlen(str2);i++){
if(str2[i]!=' '){
if(str2[i]>='a' && str2[i]<='z'){
temp2[n]=str2[i];
n++;
}else{
temp2[n]=str2[i]+32;
n++;
}
}
}
if(check_equal(temp1,temp2)){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
return 0;
}
统计单词长度
输入一行单词序列,相邻单词之间由1个或多个空格间隔,请对应地计算各个单词的长度。注意:如果有标点符号(如连字符,逗号),标点符号算作与之相连的词的一部分。没有被空格间开的符号串,都算作单词。
#include<iostream>
#include<cstring>
using namespace std;
int f=1;
char str[50];
int main(){
while(cin>>str){ //利用cin分割空格,计算长度
if(f==1)f=0;
else cout<<",";
cout<<strlen(str);
}
return 0;
}
哈希
平台最大长度
已知一个已经从小到大排序的数组,这个数组的一个平台(Plateau)就是连续的一串值相同的元素,并且这一串元素不能再延伸。例如,在
1,2,2,3,3,3,4,5,5,6中1,2-2,3-3-3,4,5-5,6都是平台。试编写一个程序,接收一个数组,把这个数组最长的平台找出
来。
#include<iostream>
using namespace std;
int map[1000]; //放main函数外面,否则初始值不是0
int main(){
int n;cin>>n;
int nums[1000];
for(int i=0;i<n;i++){
cin>>nums[i];
map[nums[i]]++; //映射
}
int max_len=-1000;
for(int i=0;i<n;i++){
max_len=max(map[nums[i]],max_len);
}
cout<<max_len<<endl;
return 0;
}
统计数字出现次数
给定一个非负整数数组,统计里面每一个数的出现次数。我们只统计到数组里最大的数。
假设Fmax(Fmax<10000)是数组里最大的数,那么我们只统计{0,1,2…Fmax}里每个数出现的次数,按顺序输出。
#include<iostream>
#include<cmath>
using namespace std;
int nums[10000];
int map[10000];
int main(){
int n;cin>>n;
for(int i=0;i<n;i++){
cin>>nums[i];
map[nums[i]]++;
}
int max_value=-1000;
for(int i=0;i<n;i++){
max_value=max(max_value,nums[i]);
}
for(int i=0;i<=max_value;i++){
cout<<map[i]<<endl;
}
return 0;
}
第一次只出现一次的字符
给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no。
#include<iostream>
#include<cstring>
using namespace std;
char str[100010];
int map_cnt[26];
int main(){
cin.getline(str,100010);
for(int i=0;i<strlen(str);i++){
map_cnt[str[i]]++;
}
for(int i=0;i<strlen(str);i++){ //按照原字符串顺序,输出第一个1
if(map_cnt[str[i]]==1){
cout<<str[i]<<endl;
return 0;
}
}
cout<<"no"<<endl;
return 0;
}