oj第六周作业题解


problem A 1081

  • 题目描述:
    有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。

  • 输入:
    初始人数n

  • 输出:
    最后一人的初始编号

  • 思路:
    利用数组和循环来模拟报数过程。

  • 代码:
#include<iostream>
using namespace std;
int main()
{
    int a[100],i,n,p=0,q;
    cin>>n;//参与的总人数
    q=n;
    for(i=0;i<n;i++) a[i]=i+1;//数组从a[0]开始标号
    for(i=0;;i++)
    {
        if(i==n) i=0;
        if(a[i]!=0) p++;//未归零(没出局的),计数(1,2,3)                           
        else continue;//当轮到的数组为零时,说明人已经出局,不进行筛选,跳出,进行下一个循环
        if(p%3==0)//p对于3取余时,,如果余数为0,说明报数的人是第三个人( 3为第一轮,6             为第二轮····),此时的a[i]就是报数的第三人
        {
            a[i]=0;//将此人归零,即出局
            q--;//总人数减少一
        }
        if(q==1) break;//总人数只剩一个人时跳出循环
    }
    for(i=0;i<n;i++)
    {
        if(a[i]!=0) cout<<a[i]<<endl;//输出剩下的人的编号为0的都已经出局
    }
    return 0;
}

probelm B 1230 小明A+B

  • 题目描述:
    小明今年3岁了, 现在他已经能够认识100以内的非负整数, 并且能够进行100以内的非负整数的加法计算. 对于大于等于100的整数, 小明仅保留该数的最后两位进行计算, 如果计算结果大于等于100, 那么小明也仅保留计算结果的最后两位. 例如, 对于小明来说: 1) 1234和34是相等的 2) 35+80=15 给定非负整数A和B, 你的任务是代表小明计算出A+B的值.

  • 输入:
    输入数据的第一行为一个正整数T, 表示测试数据的组数. 然后是T组测试数据. 每组测试数据包含两个非负整数A和B(A和B均在int型可表示的范围内).

  • 输出:
    对于每组测试数据, 输出小明A+B的结果

  • 思路:
    因为小明只会对100以内的整数进行运算,所以可以先对A,B分别取余,计算A+B,再对结果取余,但因为A,B计算前是否取余对A+B的后两位结果没有影响,所以直接计算A+B,再对结果取余即可。


problem C 1254 杨辉三角

  • 题目描述:
    还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形: 

    1
    1 
1
    1 2 1
    
1 3 3 1
    

1 4 6 4 1
    


1 5 10 10 5 1

  • 输入:
    输入数据包含多个测试实例,每个测试实例的输入只包含一个正整数n(1<=n<=30),表示将要输出的杨辉三角的层数。

  • 输出:
    对应于每一个输入,请输出相应层数的杨辉三角,每一层的整数之间用一个空格隔开,每一个杨辉三角后面加一个空行。

  • 思路:
    对于杨辉三角,每一行除了第一个和最后一个,其余的每个数都是其上一行同位置的数及前一个数的和,用一个二维数组a[i][j]表示杨辉三角的位置(i表示第几行,j表示第几个),则如果j不等于1并且不等于i,则a[i][j]=a[i-1][j]+a[i-1][j-1].如果j=1或j=i,则a[i][j]=1。

  • 优化:
    因为要输入多组数据,所以声明一个变量max=-1,当n>max时,max=n,每次只用计算从(max+1)—> n层的数据。

  • 代码:

#include <iostream>
using namespace std;
int main()
{
    int n,a[35][35],max=0;
    while (cin>>n) {
        for (int i=max; i<n; i++) {
            a[i][0]=1;a[i][i]=1;
            for (int j=1; j<i; j++) {
                a[i][j]=a[i-1][j-1]+a[i-1][j];
            }
        }
        if (n>max) max=n;
        for (int i=0; i<n; i++) {
            for (int j=0; j<i+1; j++) {
                cout<<a[i][j];
                j==i? cout<<endl:cout<<' ';
            }
        }
        cout<<endl;
    }
    return 0;
}

problem D 1259 母牛生小牛

  • 题目描述:
    设有一头小母牛,从出生第四年起每年生一头小母牛,按此规律,第N年时有几头母牛?

  • 输入:
    输入一个整数N。(1≤N≤50)

  • 输出:
    第N年时母牛的数量

  • 思路:上周我们把兔子问题都解决了,母牛问题就改改代码就行了。多列几个数,可以发现第N年的数目等于第(N-3)年的数目加第(N-1)年的数目。于是就可以用递归来解决。在递归函数中定下边界 if(n<4) return 1;。

  • 代码:

int F(int i){
    return (i<4? 1:F(i-3)+F(i-1));
}

problem E 1271 简单的事情

  • 题目描述:
    数学天才fans曾经说过一句话:组合数的计算是一件非常简单的事情。组合数的计算真的是一件非常简单的事情吗?请你自己去尝试一下吧!

  • 输入:
    输入中的一些整数对n,m(m≤n≤20)

  • 输出:
    输出其组合数。

  • 思路:
    这个题要我们求组合数,所以我们可以采用高中学习的组合数公式

    Cmn=Amnm!

    然后再用for循环一次算出 Amn 和m!,最后输出 Amnm! 的结果即可。
    核心代码求 Amn ,m!。

double mol=1,de=1;
        for(int i=1;i<=b;i++)
        {
            de*=i;
        }
        for(int i=a;i>=a-b+1;i--)
        {
            mol*=i;
        }

problem F 1402 简单求和

  • 题目描述:
    给出N个整数X1,X2,X3,…,XN,将这N个数从小到大排序为A1,A2,A3,…,AN,记数列A1,A2,A3,…,AN的奇数项之和为P,偶数项之和为Q,令T=|P-Q|,求出T的值。

  • 输入:
    第一行为正整数N(1<=N<=50000)。接下来N行每行有一个整数,按顺序给出X1,X2,X3,…,XN的值(|Xi|的值<=1000)。

  • 输出:
    输出T的值。

  • 思路:
    题目要求我们先将N个数按从小到大的顺序排序,那么我们可以用sort函数排序(不会用sort函数的同学请去看第四周题解),然后再分别求出已排好序的N个数的奇数项和及偶数项和,最后对奇数项和与偶数项和做差后取绝对值,输出这个值。

    • 有N个数,而1<=N<=50000,开一个长度为50005的数组
    • 用for循环读入N个数,(从a[1]开始更好计算)
    • 用sort函数排序
      sort(a+1,a+n+1);
    • 再用一个for循环求出数组中奇数项和及偶数项和,这里需要用if语句对i判定
    • 利用头文件cmath中的fabs函数取绝对值,然后输出
for(int i=1;i<=n;i++)
    {
        if(i%2==0)
        {
            q+=a[i];
        }
        else
        {
            p+=a[i];
        }
    }

problem G 1407 寻找子串位置

  • 题目描述:
    给出字符串a和字符串b,数据保证b是a的一个子字符串,请你输出b在a中第一次出现的位置。

  • 输入:
    仅一行包含两个字符串a和b,字符串的长度均不超过100。

  • 输出:
    仅一行一个整数

  • 解法1:
    利用for循环对a,b的每个字符进行对比。

#include <iostream>
#include <cstring>
using namespace std;
int main() {
    char a[101],b[101];
    cin>>a>>b;
    int aa=strlen(a),bb=strlen(b);
    for (int i=0; i<aa; i++) {
        bool flag=0;//用来判断是否以从i开始a,b的每个字符都相同
        if (a[i]==b[0]) {
            for (int j=1; j<bb; j++)
                if (a[i+j]!=b[j]) flag=1;
            if (flag) continue;//若有不同,则继续
            else {
                cout<<i+1<<endl;
                break;
            }
        }
    }
    return 0;
}
  • 解法2:
    直接利用find()函数,定义两个string变量a,b,然后直接利用find函数的返回值就可以轻易的求出啦(注意输出值要加1,需要头文件string)

problem H 1426 A sad story

  • 题目描述:
    Fubery found he start to fall in love with lottle school-sister Funv .
    As a university fresh man , can you ren ?
    Now , try to destroy it !
    There are 6 numbers .
    You can change the order of the 6 numbers.
    Then Funv will take the firse one and the last one , sum the up as her score.
    Finally , Fubery can take any of 3 numbers from the left 4 numbers ,and sum them up as his score .
    If Fuber’s score is smaller than Funv,s , he will lose . If bigger , he will win. if there are equal , HeHe !

  • 输入:
    There is a number T shows there are T test cases below. ( T <= 50)

For each test case , there are 6 numbers X ( 1 <= X <= 100 ).

  • 输出:
    If Fubery loses , outout “What a sad story!”
    If Fubery win , output “It will be a sad story!”
    If they are equal , output “HeHe!”

  • 思路:题目没明确说明要怎么改变排序,但很明显我们是不能ren又一个脱团潜在犯在我们眼前诞生,得让Fubery输,把第一第二大的数给Funv。Fubery也不会乖乖就范,会拿走他能拿的最大值。所以题目就成了判断前两大的数的和是否比第三四五大的数的和要大。只要排完这六个数的序,就能较简单的解决这个任务。


problem I 1431 快速幂入门

  • 题目描述:
    快速幂为我们的幂运算提供了一个很快的方法。这道题要求你练习刚刚学会的快速幂。即计算a^n。我们都知道整数能够表示的范围有限,所以这里要求让结果对100000007取模。

  • 输入:
    多组输入数据,请处理至文件结尾 每组数据包含两个整数,a与n,输入保证a和n都在32位整数能够表示的范围内,a,n>=0

  • 输出:
    a^n对100000007取模的值,每组数据的输出占一行。

  • 思路:
    写这道题首先要知道求模的公式——(a ^ n ) % h = [ ( a % h ) ^ n] % h
    但是如果就用循环一个一个求的一定时间超时(虽然显示的答案错误),所以我们需要使用快速幂,假设我们要求a^n,那么其实n是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当n=11时:
    a11=a20+21+23

    11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a20a21a23 ,也就是 a1a2a8 ,看出来快的多了吧原来算11次,现在算三次,但是这三项貌似不好求的样子….不急,下面会有详细解释。
    由于是二进制,很自然地想到用位运算这个强大的工具:&和>> &运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶x&1==0为偶,x&1==1为奇。 >>运算比较单纯,二进制去掉最后一位。
    用二进制工具只是方便理解题意,其实在本题可以用%2代替&,用/2代替>>,不多说了,放代码。
int poww(int a,int n){
    unsigned long long ans=1;
    a%=h; //h10^8+7
    while(n!=0){
        if(n&1!=0) ans=(ans*a)%h;
        a=(a*a)%h;
        n>>=1;
  }
    return ans;
}

也可以为

unsigned long long ans=1;//ans是要输出的答案 
    a%=h; //h是10^8+7
    while(n>0) //n==0跳出
    {
        if(n%2==1) ans=(ans*a)%h;//判断为奇数的情况
        n/=2;//减半
        a=(a*a)%h;
    }

problem J 1437 Letters Only

  • 题目描述:
    Coffin是一个热爱读书的Geeker。一天他在网上下载了一本PDF的电子书,发现文字里夹杂了许多非英文字符和数字,Coffin一边说这都什么玩意儿,一边开始coding想去除电子书里的非英文字符和数字。

  • 输入:
    一段字符串

  • 输出:
    去除非英文字符、标点、数字,保留英文字符、空格、换行符。

  • 思路:
    因为要保留空格,所以注意不能使用cin,只能用getline()或gets()。

  • 代码:
#include <iostream>
#include <cstring>
using namespace std;
char s[100000];//定义,用来储存输入的字符
int main()
{
    while(gets(s))//当输入字符时开始进入循环,换行时终止输入,开始进行循环(会将行末的回车符当作一个空行读入)
    {
        int n = strlen(s);//计算此行全部字符串的总长度
        for(int i=0;i<n;i++)//按所得长度进行循环
        {
            if((s[i]>='a'&&s[i]<='z')||(s[i]>='A'&&s[i]<='Z')||(s[i]==' '))//当为因为字符或空格时输出此字符,不是则进行下一个循环
            cout<<s[i];
        }
         cout<<endl;//此行字符判断完后换行
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值