• 杭电oj平台上的11页题目代码:hdu-page11 (2040~2049)2046、2048



    //2040
    #include<iostream>
    #include<algorithm>
    #define MAXN 100
    using namespace std;
    //判断a的所有的真约数之和是否等于b
    int is_N(int a,int b)
    {
    int sum1 = 0;//记录a的真约数之和
    for (int i = 1; i <= a/2; i++)
    {
    if (a%i == 0)
    {
    sum1 += i;
    }
    }
    if (sum1 == b)
    return 1;
    else
    {
    return 0;
    }
    }
    int main()
    {
    int m;
    cin >> m;
    int a, b;
    while (m--)
    {
    cin >> a >> b;
    //如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
    if (is_N(a,b)&&is_N(b,a))
    {
    cout << "YES" << endl;
    }
    else
    {
    cout << "NO" << endl;
    }
    }
    return 0;
    }

    //2041
    //思路:f1=0,f2=1;f3=2;m>2,fn=fn-1+fn-2,简单的递推
    //直接递归调用会超时
    /*ll recurrence(int m)
    {
    if (m==1)
    {
    return 0;
    }
    else if (m==2)
    {
    return 1;
    }
    else if (m==3)
    {
    return 2;
    }
    else
    {
    //递归调用
    return recurrence(m - 1) + recurrence(m - 2);
    }
    }*/
    #include<iostream>
    #include<algorithm>
    #define MAXN 40
    typedef long long ll;
    ll f[MAXN];
    using namespace std;
    void setF()
    {
    int i;
    f[1] = 0;
    f[2] = 1;
    f[3] = 2;
    for (i = 4; i <= MAXN ; i++)
    {
    f[i] = f[i - 1] + f[i - 2];
    }
    }
    int main()
    {
    int n;
    int m;
    cin >> n;
    //别忘记调用这个函数。细节问题
    setF();
    while (n--)
    {
    cin >> m;
    cout << f[m] << endl;
    }
    return 0;
    }

    //2042
    //思路:和前面一道题十分类似,简单的倒着递推
    #include<iostream>
    #include<algorithm>
    #define MAXN 31
    int f[MAXN];
    using namespace std;
    int main()
    {
    int n;
    cin >> n;
    int a;
    int i;
    f[0] = 3;
    f[1] = 4;
    f[2] = 6;
    for ( i = 3; i <= 30; i++)
    {
    f[i] = 2 * (f[i - 1] - 1);
    }
    while (n--)
    {
    cin >> a;

    cout << f[a] << endl;
    }
    return 0;
    }

    //2043
    #include<stdio.h>
    #include<string.h>
    #define MAXN 51
    char str[MAXN];
    int main()
    {
    int m;
    scanf("%d",&m);
    int count;
    int flag1, flag2, flag3,flag4;//分别用来标记是不是含有某一组的字符
    int i;
    int len;
    while (m--)
    {
    flag1 = 0;
    flag2 = 0;
    flag3 = 0;
    flag4 = 0;
    scanf("%s", str);
    len = strlen(str);
    if (!(len>=8&&len<=16))
    {
    printf("NO ");
    continue;
    }
    for (i = 0; i < len; i++)
    {
    if (str[i]>='A'&&str[i]<='Z')
    {
    flag1 = 1;
    }
    else if (str[i]>='a'&&str[i]<='z')
    {
    flag2 = 1;
    }
    else if (str[i]>='0'&&str[i]<='9')
    {
    flag3 = 1;
    }
    else if (str[i]=='~'||str[i]=='!'||str[i]=='@'||str[i]=='#'||str[i]=='$'||str[i]=='%'==str[i]=='^')
    {
    flag4 = 1;
    }
    }
    //
    if ((flag1 + flag2 + flag3 + flag4) >= 3)
    {
    printf("YES ");
    }
    else
    {
    printf("NO ");
    }
    }
    return 0;
    }

    //2044
    /*思路:从1到2 的可能路径(共1种):1->2;
    从1到3的可能路径(共2种):1->2->3, 1->3;
    从1到4的可能路径(共3种):1->2->3->4 ,1->3->4,1->2->4;
    从1到5的可能路径(共5种):1->2->3->4->5,1->2->4->5,1->3->4->5,1->2->3->5,1->3->5
    ......
    递推公式:f[n]=f[n-1]+f[n-2],注意的一点就是题目是a->b,所以看的是b-a,也就是相差的步数
    */
    #include<stdio.h>
    #include<string.h>
    #define MAXN 51
    typedef long long ll;
    ll f[MAXN];
    long long F(int a ,int b)
    {
    int n;
    n = b - a;
    f[1] = 1;
    f[2] = 2;
    if (n>2)
    {
    for (int i = 3; i < MAXN; i++)
    {
    f[i] = f[i - 1] + f[i - 2];
    }
    }
    return f[n];
    }
    int main()
    {
    int n;
    int i;
    int a, b;
    scanf("%d", &n);
    while (n--)
    {
    scanf("%d%d", &a, &b);
    printf("%lld ",F(a,b));
    }
    return 0;
    }

    //2045
    /*思路:用递推法,1)如果前n-1个格合法,则第一个格颜色和第n-1个格的颜色不同,则此时第n个格的颜色是只有一种可能颜色(因为和第一个格的颜色不能相同,还有和其相邻的第n-1格的颜色也不能相同)
    2)如果前n-1个格不合法,第n-1个格和第一个格的颜色相同,且前n-2个格合法,第n格子不能和第n-1个格和第一个格相同,所以第n个格的选择有2种*/
    #include<stdio.h>
    #include<string.h>
    #define MAXN 51
    typedef long long ll;
    ll f[MAXN];

    void setTab()
    {
    int i;
    f[1] = 3;
    f[2] = 6;
    f[3] = 6;
    for ( i = 4; i < MAXN; i++)
    {
    f[i] = f[i - 1] + 2 * f[i - 2];
    }
    }

    int main()
    {
    int n;
    setTab();
    while (~scanf("%d",&n))
    {
    printf("%lld ", f[n]);
    }
    return 0;
    }


    //2046
    #include<stdio.h>
    #include<string.h>
    #define MAXN 51
    typedef long long ll;
    ll f[MAXN];
    int main()
    {
    int n;
    f[1] = 1;
    f[2] = 2;
    f[3] = 3;
    for (int i = 4; i < 51; i++)
    {
    f[i] = f[i - 1] + f[i - 2];
    }
    while (~scanf("%d",&n))
    {
    printf("%lld ", f[n]);
    }

    return 0;
    }

    //2047
    /*递推:1)第n个元素是‘O’,那么第n-1个元素是‘E/F’即两种可能性,前n-2元素是正常f[n-2],故此时的总可能数是2*f[n-2];
    2)第n个元素是‘E/F’即两种可能,那么前n-1个元素就没有特殊的要求即f[n-1],故此时的总可能数是2*f[n-1];
    f[n]=f[n-1]+f[n-2];
    */
    #include<stdio.h>
    #include<string.h>
    #define MAXN 51
    typedef long long ll;
    ll f[MAXN];
    int main()
    {
    int n;
    f[1] = 3;
    f[2] = 8;
    for (int i = 3; i < MAXN; i++)
    {
    f[i] = 2*(f[i - 1] + f[i - 2]);
    }
    while (~scanf("%d",&n))
    {
    printf("%lld ", f[n]);
    }
    return 0;
    }

    错排的递推公式

    编辑
    当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
    第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
    第二步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
    综上得到
    D(n) = (n-1) [D(n-2) + D(n-1)]
    特殊地,D(1) = 0, D(2) = 1.

    //2048
    /*思路:题目主要的意思就是计算没有人抽到自身名字的概率,
    用错排的思想,把第n个元素放到一个位置,比如位置k,一共有n-1种方法,
    把位置k的元素放到某一个位置,可以放到位置n,那么剩下n-2个元素,f(n-2);
    可以将其不放到位置n,这时对这n-1个元素,共有f(n-1)种方法
    f(n)=(n-1)[f(n-1)+f(n-2)]
    */
    #include<stdio.h>
    #include<string.h>
    #define MAXN 21
    typedef long long ll;
    ll f[MAXN];
    ll factorial(int n)
    {
    if (n==1||n==0)
    {
    return 1;
    }
    return n*factorial(n - 1);
    }
    int main()
    {
    int n;
    ll sum;
    int m;
    double rate;
    f[1] = 0;//只有一张,故该人只能抽到自己的名字的卡片
    f[2] = 1;
    for (int i = 3; i < MAXN; i++)
    {
    f[i] = (i - 1)*(f[i - 1] + f[i - 2]);
    }
    scanf("%d", &n);
    while (n--)
    {
    scanf("%d", &m);
    sum = 0;
    rate = 0;
    //不加限制条件的总数是n!
    sum = factorial(m);
    rate = f[m]*100.0 / sum;
    printf("%.2lf\%% ", rate);
    }

    return 0;
    }

    //2049
    /*分析,该题就是求N中有M个数的错排(依然是错排,不过错排结果还要乘上C(n,m)),首先是从N个新郎中挑出会挑错新娘的M个新郎,CNM=N!/(M!*(N-M)!),
    然后再求出M个数的错排个数,递推关系:f[n]=(n-1)*(f[n-1]+f[n-2]),
    错排的情况:首先考虑,如果开始有n-1个新郎,并且这n-1个人都已经完成了错排(有f[n-1]种可能),现在又来了一个人,那么后来的第n个人可以通过用自己的新娘和那n-1个人的任意一个交换,来实现n个人都错排,这种情况有(n-1)*f[n-1]种可能;
    另外,如果开始的n-1个人不是都错排,那么要想使第n个人过来与其中一个交换后实现错排的话就必须满足两个条件:
    1.那n-1个人中只有一个人选到了自己的新娘,也就是说有n-2个人都已经错排了,
    2.第n个人必须和那个选到自己的新娘的人去交换,但那个选到自己的新娘的人可以是n-1个人中的任意一个。这种情况有(n-1)*f[n-2]种可能*/
    #include<stdio.h>
    #include<string.h>
    #define MAXN 21
    typedef long long ll;
    ll f[MAXN];
    //阶乘函数
    ll factorial(int n)
    {
    if (n == 1 || n == 0)
    {
    return 1;
    }
    return n*factorial(n - 1);
    }
    int main()
    {
    int c;
    int n, m;
    ll sum;
    scanf("%d", &c);
    f[0] = 0;
    f[1] = 0;
    f[2] = 1;
    f[3] = 2;
    for (int i = 4; i < MAXN; i++)
    {
    f[i] = (i - 1)*(f[i-1]+f[i-2]);
    }
    while (c--)
    {
    sum = 0;
    scanf("%d%d", &n, &m);
    sum = factorial(n) / factorial(m) / factorial(n - m);
    sum *= f[m];
    printf("%lld ", sum);
    }
    return 0;
    }

    一生有所追!
  • 相关阅读:
    bzoj4137[FJOI2015]火星商店问题
    HNOI2019游记
    bzoj4785:[ZJOI2017]树状数组:二维线段树
    快速傅里叶变换(FFT)
    动规大总结
    复习动规(4)
    复习动规(3)
    复习动规(2)
    复习动规(1)
    2019CSP-S游记(真)
  • 原文地址:https://www.cnblogs.com/BlueBlue-Sky/p/8591852.html
Copyright © 2020-2023  润新知