首页 > Web开发 > 详细

BZOJ4475[Jsoi2015]子集选取——递推(结论题)

时间:2019-03-02 11:34:35      阅读:161      评论:0      收藏:0      [点我收藏+]

题目描述

技术分享图片

输入

输入包含一行两个整数N和K,1<=N,K<=10^9

输出

一行一个整数,表示不同方案数目模1,000,000,007的值。

样例输入

2 2

样例输出

16
 
可以发现对于集合中每个元素的选取都是互不影响的,设$f(n,k)$为输入$n,k$时的答案,那么$f(n,k)=f(1,k)^n$。
我们现在来推导$f(1,k)$的结果:可以发现$1$的位置一定是连续的,设$a_{i}$表示第$i$列最后选取到了$a_{i}$行,若从第$1$列到第$m$列均存在被选取。
那么可以得到结论:$a_{i+1}\le a_{i}(1\le i <m)$。
设$g[i][j]$代表第$i$列最后选取到了第$j$行,可以得到递推式:$g[i][j]=\sum\limits_{p=j}^{k}g[i-1][p]$。
通过观察可以得到:$g[i][j]=g[i-1][j]+g[i][j+1]$,这实际上就是一个顺时针旋转了$45^{\circ}$的杨辉三角。
那么加上都不选取的方案数,$f(1,k)=1+\sum g[i][j]=2^k$,由此可得$f(n,k)=2^{nk}$。
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,k;
int mod=1000000007;
ll quick(ll x,ll y)
{
	ll res=1;
	while(y!=0)
	{
		if(y%2==1)
		{
			res=(res*x)%mod;
		}
		x=(x*x)%mod;
		y/=2;
	}
	return res%mod;
}
int main()
{
	scanf("%d%lld",&n,&k);
	ll sum=1ll*n*k;
	printf("%lld",quick(2,sum));
}

BZOJ4475[Jsoi2015]子集选取——递推(结论题)

原文:https://www.cnblogs.com/Khada-Jhin/p/10460244.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!