HDU 4602 Partition (计数方法+组合知识)*

Partition

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3582    Accepted Submission(s): 1402


 

Problem Description

Define f(n) as the number of ways to perform n in format of the sum of some positive integers. For instance, when n=4, we have
  4=1+1+1+1
  4=1+1+2
  4=1+2+1
  4=2+1+1
  4=1+3
  4=2+2
  4=3+1
  4=4
totally 8 ways. Actually, we will have f(n)=2(n-1) after observations.
Given a pair of integers n and k, your task is to figure out how many times that the integer k occurs in such 2(n-1) ways. In the example above, number 1 occurs for 12 times, while number 4 only occurs once.

 

Input

The first line contains a single integer T(1≤T≤10000), indicating the number of test cases.
Each test case contains two integers n and k(1≤n,k≤109).

 

Output

Output the required answer modulo 109+7 for each test case, one per line.

 

Sample Input

 

2 4 2 5 5

 

Sample Output

 

5 1

 

Source

2013 Multi-University Training Contest 1

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

 

#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
/*
题目大意:已知n有2^(n-1)种拆分的方法,
那么给定k,计数k在所有拆分方法中出现的次数。

数学题,这道题原本我想烦了。。。
是用数学递推来处理的,但是有太多细节了并且初始情况是F(k,k)=1,
这就更加麻烦了,递推方式的思想也很简单f(n,k)=2^(n-k-1)+sigma i:0~n-1 f(i,k);
这样种方式运行下去,可以得到f(n,k)=2^(n-k-1)+2f(n-1,k);要嵌套一些母函数来处理,最终得到的结果应该是差不多的。

但是不妨用组合计数的方式来思考处理。。。
考虑n个1全铺开,如果k个连续就是当成分解中的k,
那么计数k的方法只要计数这样的连续出现的位置,对于每种位置,
有多少种即可,不会产生重复,因为是以位置来考虑,贡献的思想,每个位置对答案贡献了多少。

分类一下,考虑在中间和在两端的结果,不难得到答案为2^(n-k-2)*(n-k-1)+2^(n-k)
*/

const int  maxn =3e3+5;
const int mod=1e9+7;

ll powmod(ll x,ll y){ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}
ll n,k;

int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%dlld",&n,&k);
        if(k>n) puts("0");
        else if(n==k+1)  puts("2");
        else if(n==k) puts("1");
        else
        {
            ll tp=powmod(2LL,n-k-2)*(n-k-1)%mod+powmod(2LL,n-k);
            tp%=mod;
            printf("%lld\n",tp);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/82081600