Hrbust-1132 水数(排列组合)

这里写图片描述

就是找n位的二进制数里有多少个1,全部求和即可,基本上就是排列组合,求所有数字中1的出现次数,然后求和。
因为求组合数是有规律的,这里又需要求和累加操作,因此用一个数塔递推计算即可。主要还是得想到排列组合时形成的规律

1 ——> 1 ——> 1×1=1
2 ——> 1 1 ——> 1×1+2×1=3 ——> =1×2+1
3 ——> 1 2 1 ——> 1×1+2×2+3×1=8 ——> =3×2+2
4 ——> 1 3 3 1 ——> 1×1+2×3+3×3+4×1=20 ——> =8×2+4
5 ——>1 4 6 4 1 ——> 1×1+2×4+3×6+4×4+5×1=48 ——> =20×2+8
…………………….

从中打表后又可得到规律,每次的答案是上一轮答案*2+2的幂次。最后打表即可

代码如下:

#include<stdio.h>///对数字1的排列组合排列组合,然后1的个数就排列组合后直接*有几个1
#include<string.h>
int a[30][30],n,ans[30],t;
int main()
{
    for(int i=1; i<=25; i++)a[i][i]=1;
    for(int i=2; i<=25; i++)a[i][1]=1;
    for(int i=3; i<=25; i++)
        for(int j=2; j<i; j++)
            a[i][j]=a[i-1][j-1]+a[i-1][j];
    memset(ans,0,sizeof(ans));
    for(int i=1; i<=25; i++)
        for(int j=1; j<=i; j++)
            ans[i]+=a[i][j]*j;
    scanf("%d",&t);
    while(t--) scanf("%d",&n),printf("%d
",ans[n]);
}

打表代码:

#include<stdio.h>
int main()
{
    int a[26],pow=1,t,n;a[1]=1;
    for(int i=2;i<=25;i++)
        a[i]=a[i-1]*2+pow,pow*=2;
    scanf("%d",&t);
    while(t--)scanf("%d",&n),printf("%d
",a[n]);
}
/*
这个规律是把上一层的每个二进制数中加入0或1组成本层的二进制数,
这样本层的“1”的个数就是上层的结果*2+所加的1的个数
*/
原文地址:https://www.cnblogs.com/kuronekonano/p/11135853.html