类型1 求素数
例1,1
素数个数统计
,统计100到300之间素数共有多少个,计算所有素数的和并输出结果
时间复杂度o(n2)
#include <stdio.h>
void main()
{
int i,j,n=0,sum=0;
for(i=100;i<=300;i++)
{
for(j=2;j<i;j++)
if(i%j==0) break;
if(j>=i) {n++;sum+=i;}
}
printf("100到300之间共有%d个素数,和为%d",n,sum);
}
2素数筛法—欧拉线性筛 目前没看懂
3质因数分离
首先看一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻。例如5和7,11和13,17和19等等;
证明:令x≥1,将大于等于5的自然数表示如下:
··· 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ···
可以看到,不在6的倍数两侧,即6x两侧的数为6x+2,6x+3,6x+4,由于2(3x+1),3(2x+1),2(3x+2),所以它们一定不是素数,再除去6x本身,显然,素数要出现只可能出现在6x的相邻两侧。因此在5到sqrt(n)中每6个数只判断2个,时间复杂度O(sqrt(n)/3)。
#include <iostream>
#include <cmath>
using namespace std;
int isPrime(int n)
{ //返回1表示判断为质数,0为非质数,在此没有进行输入异常检测
float n_sqrt;
if(n==1) return 0;
if(n==2 || n==3) return 1;
if(n%6!=1 && n%6!=5) return 0;
n_sqrt=floor(sqrt((float)n));
for(int i=5;i<=n_sqrt;i+=6)
if(n%(i)==0 || n%(i+2)==0) return 0;
return 1;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
if(isPrime(i)) cout<<i<<" ";
}
return 0;
}
例1.2
A % B 问题(amodb)
问题描述
本题(几乎)等价于洛谷 P1865,因此 0xis 直接搬运了原题名称。本题询问区间质数个数(注意,“输出格式”有重要信息)。
输入格式
第一行两个整数,范围 n 和询问次数 m。
之后 m 行,每行两个整数 l 和 r 代表区间。
输出格式
对每次询问,输出一行一个整数代表闭区间 [l, r] 内质数个数。
“闭区间”包含两端,如 [2, 5] 指 {2, 3, 4, 5}。
输入样例一
5 2
1 3
4 5
输出样例一
2
1
数据范围与约定
对 30% 数据,n <= 100。
对 70% 数据,n <= 10000。
对所有数据,n <= 500000,m <= 1000,1 <= l < r <= n。
类型2 进位制转换
案例2.1 外星旅行(traval)
问题描述
现代科学中有一派理论认为,之所以人们普遍采用十进制计数法是由于人一共有十只手指。
有一天,西蒙•胡塞•德•拉•桑迪西玛搭乘宇宙飞船去X星旅行,当地人一共有k只手指,也就是说,当地人在交流时使用的进制是k进制。
于是问题来了,西蒙•胡塞•德•拉•桑迪西玛在与当地人交流时必须把十进制的数字转变为k进制,这使他烦不胜烦,于是西蒙•胡塞•德•拉•桑迪西玛请求你来帮助他,
并且他希望倒序输出所有的结果。
输入格式
第一行为两个正整数n和k, 其中k为X星人采用的进制,n为待转变为k进制的数字的个数。
第2-n+1行各给出一个待转变的十进制正整数。
输出格式
输出共计n行,其中第i行为一个k进制整数,为第n-i+1个正整数转变后的结果(1<=i<=n)。
输入样例
3 8
16
27
39
输出样例
47
33
20
提示: 使用函数进行处理。
数据范围与约定
对于100%的数据,n<=10^5, 2<=k<=10, 其他十进制数字在1到2^50之间。
案例2.2
外星旅行(traval)变式
现代科学中有一派理论认为,之所以人们普遍采用十进制计数法是由于人一共有十只手指。
有一天,西蒙•胡塞•德•拉•桑迪西玛搭乘宇宙飞船去X星旅行,当地人一共有k只手指,也就是说,当地人在交流时使用的进制是k进制。
于是问题来了,西蒙•胡塞•德•拉•桑迪西玛在与当地人交流时必须把十进制的数字转变为k进制,这使他烦不胜烦,于是西蒙•胡塞•德•拉•桑迪西玛请求你来帮助他,
并且他希望倒序输出所有的结果。
输入格式
第一行为两个正整数n和k, 其中k为X星人采用的进制,n为待转变为k进制的数字的个数。
第2-n+1行各给出一个待转变的十进制正整数。
输出格式
输出共计n行,其中第i行为一个k进制整数,为第n-i+1个正整数转变后的结果(1<=i<=n)。
输入样例
3
16 8
27 4
39 7
输出样例
20
123
54
提示: 使用函数进行处理。
数据范围与约定
对于100%的数据,n<=10^5, 2<=k<=10, 其他十进制数字在1到2^50之间。
例2
例3 10进制转化成任意进制
#include <iostream>
using namespace std;
int main()
{
long n;
int p,c,m=0,s[100];
cout<<"输入要转换的数字:"<<endl;
cin>>n;
cout<<"输入要转换的进制:"<<endl;
cin>>p;
cout<<"("<<n<<")10="<<"(";
while (n!=0)//数制转换,结果存入数组s[m]
{
c=n%p;
n=n/p;
m++;s[m]=c; //将余数按顺序存入数组s[m]中
}
for(int k=m;k>=1;k--)//输出转换后的序列
{
if(s[k]>=10) //若为十六进制等则输出相对应的字母
cout<<(char)(s[k]+55);
else //否则直接输出数字
cout<<s[k];
}
cout<<")"<<p<<endl;
return 0;
}
例3 利用递归实现10进制转化成任意进制
#include<iostream>
#include<cstring>
using namespace std;
void translation(char *s,int a,int b);
int main(){
cout<<"请输入要转化的数字";
int a ,b;
cin>>a;
cout<<"请输入要转化的进制";
cin>>b;
char s[80];
translation(s,a,b);
cout<<s<<endl;
}
void translation(char *s,int a,int b){
int lengt;
char str[]={"0123456789ABCDEF"};
if(a==0){
strcpy(s,"");
return;
}
translation(s,a/b,b);
lengt= strlen(s);
s[lengt]=str[a%b];
s[lengt+1]='\0';
}
类型3 字符串子集
/*
例3.1_验证子串
Copyright:
Author:
Date: 01-09-17 22:06
Description: 18_验证子串
查看 提交 统计 提问
总时间限制: 1000ms 内存限制: 65536kB
描述
输入两个字符串,验证其中一个串是否为另一个串的子串。
输入
输入两个字符串,每个字符串占一行,长度不超过200且不含空格。
输出
若第一个串s1是第二个串s2的子串,则输出(s1) is substring of (s2)
否则,若第二个串s2是第一个串s1的子串,输出(s2) is substring of (s1)
否则,输出 No substring。
样例输入
abc
dddncabca
样例输出
abc is substring of dddncabca
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 201;
char S1[N],S2[N];
int main()
{
gets(S1); gets(S2);
if (strlen(S1) >= strlen(S2))
{
if (strstr(S1, S2) != NULL)
cout << S2 << " is substring of " << S1 << endl;
else
cout << "No substring" << endl;
}
else
{
if (strstr(S2, S1) != NULL)
cout << S1 << " is substring of " << S2 << endl;
else
cout << "No substring" << endl;
}
return 0;
}
法2
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
char s1[200],s2[200];
gets(s1);//获取字符串s1
gets(s2);//获取字符串s2
if(strstr(s2,s1))//判断s1是否是s2的子串
{
cout<<s1<<" is substring of "<<s2<<endl;
return 0;
}
if(strstr(s1,s2))//判断s2是否是s1的子串
{
cout<<s2<<" is substring of "<<s1<<endl;
return 0;
}
cout<<"No substring"<<endl;
return 0;
}
**
类型4 冒泡排序
**
例4.1难度排序
问题描述
老韩让书名号出一道简单题,于是他出了n道题(1-n),让鱼人们去做,并让它们给出每道题的普通指数ai,你能帮帮书名号,帮他把题目按照普通度排序么?
一句话题意:给出n个权值,按照权值从小到大将编号排序。
数据保证权值不重复。
输入格式
第一行一个整数n,代表题目的数量。
第二行n个数字,代表每道题的权值。
输出格式
一行,数字间用空格隔开。
输入样例
10
10 20 30 40 90 80 70 60 50 100
输出样例
1 2 3 4 9 8 7 6 5 10
数据范围与约定
0<=n<=1000000,0<=ai<=1000000。
提示:对于30%的数据,O(n²)会TLE,也许你可以先看看下一道题?
法1 可得70分
#include<iostream>
using namespace std;
int a[1000010];
int p[1000010];
int main()
{
//设变量
int n,i,j;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
p[i]=i;
//输入数组
for(i=1;i<=n-1;i++)
{
for(j=1;j<=n-i;j++)
if(a[j]>a[j+1])
{
int t;
t=a[j+1];
a[j+1]=a[j];
a[j]=t;
t=p[j];
p[j]=p[j+1];
p[j+1]=t;
}
}
int flag=1;
for(i=1;i<=n;i++)
{
if(flag)
{cout<<p[i];
flag=0;
}
else cout<<" "<<p[i];
}
//冒泡排序
return 0;
}
法2 二维数组 70分
#include<iostream>
using namespace std;
int a[1000010][2];
int main()
{
//设变量
int n,i,j;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i][0];
a[i][1]=i;
}//输入数组
for(i=1;i<=n-1;i++)
{
for(j=1;j<=n-i;j++)
if(a[j][0]>a[j+1][0])
{
int t;
t=a[j+1][0];
a[j+1][0]=a[j][0];
a[j][0]=t;
t=a[j][1];
a[j][1]=a[j+1][1];
a[j+1][1]=t;
}
}
int flag=1;
for(i=1;i<=n;i++)
{
if(flag)
{cout<<a[i][1];
flag=0;
}
else cout<<" "<<a[i][1];
}
//冒泡排序
return 0;
}
法三 结构体 不知道多少分,但很简单
#include<iostream>
#include<cmath>
using namespace std;
struct item{
int ai;
int no;
};
item d[1000010];
int n;
int main(){
cin>>n;
for(int i=1; i<=n; i++){
cin>>d[i].ai;
d[i].no=i;//结构体输入 相当如标记每个难度
}
//冒泡排序
for(int i=1; i<n; i++){
for(int j=1; j<=n-i; j++)
if(d[j].ai>d[j+1].ai){
item t=d[j];//d[j]的数据整体给了t
d[j]=d[j+1];
d[j+1]=t;
}
}
for(int i=1; i<n; i++)
cout<<d[i].no<<" ";//控制最后一个后面没有空格
cout<<d[n].no<<endl;
return 0;
}
例4.2 求众数
问题描述
老韩让书名号出一道简单题,于是他出了n道题(1-n),让鱼人们去做,并让它们说出最简单的一道题,但鱼人们众口不一,你能帮帮书名号,帮他选出来最简单的题么?
一句话题意:给出n个数,求众数,若众数不唯一,请按数字顺序依次输出。
输入格式
第一行两个整数n,m,代表题目的数量和鱼人的数量。
第二行m个数字,代表每个鱼人认为最简单题目的编号。
输出格式
一行,数字间用空格隔开。
输入样例
5 11
1 2 3 4 5 1 2 3 4 5 1
输出样例
1
数据范围与约定
n,m<=10000000,对于30%的数据保证众数唯一。
方法 用桶计数
#include<iostream>
using namespace std;
int d[10000010];
int main(){
int n, m;
cin>>n>>m;
//使用桶计数
for(int i=1; i<=m; i++){
int no;
cin>>no;
d[no]++;
}
//找难度最大的题的难度
int zdz=-1;
for(int i=1; i<=n; i++)
if(d[i]>zdz)
zdz=d[i];
//找难度最大的题的题号
int flag=1;
for(int i=1; i<=n; i++)
if(d[i]==zdz)
if(flag){
cout<<i;
flag=0;
}else
cout<<" "<<i;//众数不一定是一个数,如果是多个,最后不能输出空格
return 0;
}
桶的应用2
斐波那契数列打表法
就是名字叫十一的无聊的小女孩想自己给自己改个名字,她的“mdzz”好朋友说你的名字应该只含有’O’和’o’,并且当它所在的位数为斐波那契数时为’O’,否则为’o’给你了一个n代表改完后的名字的长度
思路:
直接斐波那契打一个标记表 然后一层for循环判断输出就ojbk
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=10010;
int flag[N];//标记数组
int m[N];//斐波那契数组
int main()
{
int n;
m[1]=1;
m[2]=1;
flag[1]=1;
for(int i=3;i<=20;i++)//n小于等于1000 打到20都有点大
m[i]=m[i-1]+m[i-2],flag[m[i]]=1;
cin>>n;
for(int i=1;i<=n;i++)//判断输出
{
if(flag[i]==1)
cout<<"O";
else
cout<<"o";
}
cout<<endl;
return 0;
}
类型5 递归
------
案例1 求最大公约数的简易求法
include
using namespace std;
int main()
{
int a,b,c;
cin>>a>>b;
while(a%b!=0)
{
c=a%b;
a=b;
b=c;
}
cout<
用递归求最大公约数
include
using namespace std;
int gcd(int a,int b) //求最大公约数 当b为0时结束递归
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
int main()
{
int a,b;
cin>>a>>b;
cout<