暑期测试2 题目积累中

类型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<

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值