2018暑假楼下集训第一场(递推,递归,素数筛选)

A - Fibbonacci Number
题解:求斐波那契数列(注意:开 long long )

#include <iostream>

using namespace std;

long long  f[60];
//打表
void init()
{
    f[0]=0;
    f[1]=1;
    for (int i=2;i<=50;i++)
        f[i]=f[i-1]+f[i-2];
}
int main()
{
    int n;
    init();
    while (~scanf("%d",&n))
    {
        if (n==-1)
            break;
        printf("%lld\n",f[n]);
    }
        return 0;
}

B - 神、上帝以及老天爷
题意:有n为宾客,以及写着每位宾客名字的纸条,每位宾客从所有写着名字的纸条中不放回的抽取一张,问每位宾客抽到的纸条上的名字都不是自己名字的概率(用百分号形式表示)
题解:假设有n为宾客,每个纸条按照宾客抽取的顺序进行编号,第一位宾客从剩余的n-1个帽子抽取了第k个纸条,而k有n-1种可能性,恰好第k位宾客也抽取到第1为宾客的纸条,,所以此时f(n)=(n-1)*f(n-2);但是如果第k为宾客没有抽取到第1张纸条,则f(n)=(n-1)*f(n-1)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
using namespace std;
long long a[25];
long long b[25];
//打表递推公式f(n)=(n-1)*f(n-1)+(n-1)*f(n-2)
void init1()
{
    a[1]=0;
    a[2]=1;
    for (int i=3;i<=20;i++)
        a[i]=(i-1)*(a[i-1]+a[i-2]);
}
//打表,n个取纸条,所有的可能性
void init2()
{
    b[0]=b[1]=1;
    b[2]=2;
    for (int i=3;i<=20;i++)
        b[i]=b[i-1]*i;
}
int main()
{
    int n,m;
    init1();
    init2();
    scanf("%d",&n);
    while (n--)
    {
       scanf("%d",&m);
       printf("%.2lf%%",a[m]*1.0/b[m]*1.0*100);
        puts("");
    }
    return 0;
}

C - 母猪的故事
题意: ACBoy要养猪,每头猪在出生后的第二天开始以后每天都会生下一头猪,而且生下的都是母猪,但是在一头猪生下第二头猪的后,会被卖到超市,问在第n天会有多少头猪
题解: 递推

天数 年龄为1 年龄为2 年龄为3 总的数量
1 1 0 0 1
2 1 1 0 2
3 2 1 1 3
4 3 2 1 5
5 5 3 2 8
6 8 5 3 13

某天年龄为1的猪的数量为前一天猪的数量的总量,年龄为2的猪的数量为前一天年龄为1的猪的数量,年龄为3的猪的数量为前一天年龄为2的猪的数量(被卖入超市不计数)

//解法一:打表
#include <iostream>

using namespace std;

long long  f[21];
void init()
{
    f[1]=1;
    f[2]=2;
    for (int i=3;i<=20;i++)
        f[i]=f[i-1]+f[i-2];
}
int main()
{
    int n;
    init();
    int m;
    scanf("%d",&m);
    while (m--)
    {
        scanf("%d",&n);
        printf("%lld\n",f[n]);
    }
    return 0;
}
//解法二:递归
#include <iostream>

using namespace std;

long long  f[21];
long long  init(int m)
{
    if (m==1)
        return 1;
    if (m==2)
        return 2;
    return init(m-1)+init(m-2);
}
int main()
{
    int n;
    int m;
    scanf("%d",&m);
    while (m--)
    {
        scanf("%d",&n);
        printf("%lld\n",init(n));
    }
    return 0;
}

D - 下沙的沙子有几粒?
题意: 告诉你H的数量和D的数量,问有H D有多少种排列的顺序使得,从左开始数H的数量始终大于等于D的数量,例如3个H和1个D,HHHD,HHDH,HDHH ,有三种排列方式
题解: 当D的数量n大于H的数量m时,不存在这种排列。a[m][n]=a[m-1][n]+a[m][n-1],假设3个H和2个D是由2个H和2个D还有3个H一个D推来的,2个H和2个D总共有HDHD,HHDD两种排列,3个H和一个D总共有HDHH,HHDH,HHHD三种排列,然后在HDHD,HHDD的后面添加一个H就是2种排列,在HDHH,HHDH,HHHD的后面添加一个D就有3种方案,所以总共就是5种方案(其它的添加方法都是重复的)

#include<stdio.h>
#include<string.h>
int main()
{
    long long  a[21][21];
    int i,j,m,n;
    memset(a,0,sizeof(a));//首先全部初始化为0
    for(i=0; i<=20; i++)
        a[i][0]=1;//当n为0的时候无论吗取何值都是1
    for(i=1; i<=20; i++)
        for(j=i; j<=20; j++)
            a[j][i]=a[j-1][i]+a[j][i-1];
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        printf("%lld\n",a[m][n]);
    }
    return 0;
}

E - 算法:骨牌铺方格
题解: n代表长方形方格的长度,当第一个骨牌竖着放入长方形方格中,第一个骨牌已经固定,长方形方格还剩2×(n-1)的空间,则F(n)=F(n-1);当第一,二张骨牌横着放入长方形方格,长方形方格还剩2×(n-2)的空间,则F(n)=F(n-2)。所以根据开头放骨牌的方式,F(n)=F(n-1)+f(n-2)。(此题不可以用递归方式写,递归的时间复杂度太高了,会超时!)

#include<stdio.h>
#include<string.h>
long long f[60];
void init()
{
     f[1]=1;
     f[2]=2;
    for (int i=3;i<=50;i++)
        f[i]=f[i-1]+f[i-2];
}
int main()
{
    int n;
    init();
    while (~scanf("%d",&n))
    {
        printf("%lld\n",f[n]);
    }
    return 0;
}

F - 蟠桃记
题解: 递推F(n-1)=( F(n)+1 )*2

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
using namespace std;
int main()
{
    int n;
    while (~scanf("%d",&n))
    {
        int ans=1;
        while (--n)
        {
            ans=(ans+1)*2;
        }
        printf("%d\n",ans);
    }
    return 0;
}

H - Sum of Consecutive Prime Numbers

题意: 给定一个10000以内的数,如果这个数字可有几个连续的素数的相加得到,问这样的连续的素数有几组
题解: 最笨的方法,先把所有的素数打表找出来,然后跑两层循环找

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=1e4+7;
int prime[N];
void GetPrime()
{
    memset(prime,0,sizeof(prime));
    for (int i=2;i<N;i++)
    {
        if (prime[i]==0)
            prime[++prime[0]]=i;
        for (int j=1;j<=prime[0]&&prime[j]<=N/i;j++)
        {
            prime[prime[j]*i]=1;
            if (i%prime[j]==0)
                break;
        }
    }
}
int main()
{
    int n;
    GetPrime();
    while (~scanf("%d",&n)&&n)
    {
       int sum=0, ans=0;
        for (int i=1;i<=prime[0];i++)
        {
            sum=0;
            for (int j=i;j<=prime[0]&&sum<n;j++)
            {
                sum+=prime[j];
                if (sum==n)
                    ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

I - 不容易系列之二
题解: 和蟠桃记一样递推,简单的数学题

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=1e4+7;
int prime[N];
int a[35];
void init()
{
    a[0]=3;
    for (int i=1;i<=30;i++)
    {
        a[i]=(a[i-1]-1)*2;
    }
}
int main()
{
    int n,m;
    init();
    scanf("%d",&n);
    while (n--)
    {
        scanf("%d",&m);
        printf("%d\n",a[m]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39535750/article/details/81078313