肥宅快乐数

肥宅快乐数

Time limit:1s Memory limit:128M

Description

作为一个肥宅,栗酱每天都从不同的事物上获得快乐。今天他发现每一个形如 (i,j) 的二元组当满足 “i + j == i | j” 时都会给他带来1点快乐。现在问题来了,[1, 2^k] 以内的正整数一共能带给栗酱多少点快乐呢?

答案对1e+7取模

Input

数据的第一行是数据组数T

在每组数据中:第一行是一个整数k

T <= 128

k <= 128

Output

每组数据一行,直接输出答案。

Sample Input

2

1

10

Sample Output

2

59048

HINT

(2,1)(1,2)算不同的二元组

 

 

这是我参加的2018年绍兴市市赛的一道题,当时做此题时因组合数过大不会处理而未能做出此题,回来之后参考了一些资料成功解出来了,现补上代码,纪念我的第一道组合数取余。

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int mod=1e9+7;
int c[130][130];
int quick_pow(int n,int m){
    int ans=1;
    while(m){
        if(m&1)
        ans=1ll*ans*n%mod;
        n=1ll*n*n%mod;
        m>>=1;
    }
    return ans;
}
//这个comb用来求组合数取余,借鉴了https://blog.csdn.net/u012860428/article/details/41317231大佬的代码针对这题优化了一下
int comb(int n,int m){
    int ans=1;
    for(int i=1;i<=m;i++){
        int x=n-m+i;
        ans=ans*(1ll*x*quick_pow(i,mod-2)%mod)%mod;
    }
    return ans;
}
int main(){
    for(int i=1;i<=128;i++){
        c[i][0]=1;
        for(int j=1;j<=i;j++){
            if(j>(i>>1))c[i][j]=c[i][i-j];
            else c[i][j]=comb(i,j);
        }
    }
    for(int i=1;i<=100;i++)
    printf("%d ",c[100][i]);
    int T,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        //当i等于1<<n时,j只要小于1<<n都满足题目要求,同样当j等于1<<n时,i只要小于1<<n也满足要求,这里一个有(1<<n+1)-2个二元组
        int ans=quick_pow(2,n+1)-2;
        //现在i或j等于1<<n的情况都考虑过了,再来考虑i和j都不等于1<<n的情况
        //也就是在n个2进制位里随意取i个为1,组成的数为题目所说的i,在剩下的n-i个二进制位里随意取j个二进制位为1,组成的数为题目所说的j
        //但是为了满足i和j大于等于1的要求,所以i不能把n个二进制位都取完,所以循环里用i<n
        for(int i=1;i<n;i++)
        ans=(ans+(1ll*quick_pow(2,n-i)-1)*c[n][i])%mod;
        printf("%d\n",ans);
    }
    return 0;
}

大佬的组合数取余代码如下(前提是p为素数)转自:https://blog.csdn.net/u012860428/article/details/41317231

#include <iostream>
#include <string.h>
#include <stdio.h>
 
using namespace std;
typedef long long LL;
 
LL n,m,p;
 
LL quick_mod(LL a, LL b)
{
    LL ans = 1;
    a %= p;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}
 
LL C(LL n, LL m)
{
    if(m > n) return 0;
    LL ans = 1;
    for(int i=1; i<=m; i++)
    {
        LL a = (n + i - m) % p;
        LL b = i % p;
        ans = ans * (a * quick_mod(b, p-2) % p) % p;
    }
    return ans;
}
 
LL Lucas(LL n, LL m)
{
    if(m == 0) return 1;
    return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
 
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%I64d%I64d%I64d", &n, &m, &p);
        printf("%I64d\n", Lucas(n,m));
    }
    return 0;
}

 

posted @ 2018-11-27 21:03  Jathon-cnblogs  阅读(277)  评论(0编辑  收藏  举报