bzoj千题计划263:bzoj4870: [六省联考2017]组合数问题
http://www.lydsy.com/JudgeOnline/problem.php?id=4870

80分暴力打的好爽 \(^o^)/~

预处理杨辉三角

令m=n*k
要求满足m&x==x ,x<=m, x%k==r 的x的个数
结论:若n&m==m,则C(n,m)为奇数,否则为偶数
枚举m的子集,判断是否%k==r
时间复杂度:O(m的位子集个数),即O(2^(m的二进制中1的个数))极限是O(n*k)

杨辉三角第i行的和=2^i,即
那么用2^(nk) 减去 前面不用的C
因为r<=50,所以这种C的个数<=50
暴力计算C即可

k=2 就是C(2n,r)+C(2n,r+2)+C(2n,r+4)……
是隔一个加一个
杨辉三角 每一行的 奇数列之和=偶数列之和
所以 2^(2n)/2 - 前面不用的C,也是隔一个减一个
除2的计算 要乘2的逆元,但是p不是素数
所以 计算2^(2n) 改成计算 2^(2n-1)

预处理阶乘和阶乘的逆元,枚举计算C ,最多会计算n个C

不会,求指点

考虑组合数C(n,m)的实际意义:从n个元素里选出m个元素的方案数
那么本题就是求从n*k个元素里,选出%k=r个元素的方案数
dp[i][j] 表示从前i个元素里,选出%k=j 个元素的方案数
第i个不选:dp[i][j]+=dp[i-1][j]
第i个选:dp[i][j]+=dp[i-1][(j-1+k)%k]
矩阵乘法优化

#include<cstdio>
#include<cstring> using namespace std; int p,K; int a[][],ans[][],f[][]; int C[][]; void mul(int A[][],int B[][])
{
memset(C,,sizeof(C));
for(int i=;i<K;++i)
for(int j=;j<K;++j)
for(int k=;k<K;++k)
C[i][j]=(C[i][j]+1LL*A[i][k]*B[k][j]%p)%p;
for(int i=;i<K;++i)
for(int j=;j<K;++j)
A[i][j]=C[i][j];
} int main()
{
int n,k,r;
scanf("%d%d%d%d",&n,&p,&K,&r);
for(int i=;i<=K-;++i) a[i][i]=a[i][i+]=;
a[K-][K-]++; a[K-][]++;
f[][]=;
for(int i=;i<K;++i) ans[i][i]=;
long long m=1LL*n*K;
for(;m;mul(a,a),m>>=)
if(m&) mul(ans,a);
mul(f,ans);
printf("%d",f[][r]);
}
AC代码
#include<cstdio>
#include<cstring> using namespace std; typedef long long LL; int n,p,k,r; int C[][]; int num[]; int inv[],fac[]; LL xx; void ADD(int &x,int y)
{
xx=x;
xx+=y;
xx-=xx>=p ? p : ;
x=xx;
} void YangHui()
{
C[][]=;
int m=n*k;
for(int i=;i<=m;++i)
{
C[i][]=;
for(int j=;j<=m;++j) C[i][j]=(1LL*C[i-][j]+C[i-][j-])%p;
}
int ans=;
for(int i=;i<=n;++i)
{
if(i*k+r>m) break;
ADD(ans,C[m][i*k+r]);
}
printf("%d",ans);
} void Yu()
{
LL m=1LL*n*k;
int ans=;
for(LL t=m;t;t=(t-)&m)
if(t%k==r) ans^=;
printf("%d",ans);
} int Pow(int a,int b)
{
int res=;
for(;b;a=1LL*a*a%p,b>>=)
if(b&) res=1LL*res*a%p;
return res;
} int get_gcd(int a,int b)
{
return !b ? a : get_gcd(b,a%b);
} int get_C(int m,int k)
{
for(int i=m-k+;i<=m;++i) num[i]=i;
int x,gcd;
for(int i=;i<=k;++i)
{
x=i;
for(int j=m-k+;j<=m && x!=;++j)
{
gcd=get_gcd(num[j],x);
num[j]/=gcd;
x/=gcd;
}
}
int ans=;
for(int i=m-k+;i<=m;++i) ans=1LL*ans*num[i];
return ans;
} void PreSum()
{
int a=Pow(,n);
int b=;
for(int i=;i<r;++i) ADD(b,get_C(n,i));
a-=b;
if(a<) a+=p;
printf("%d",a);
} void JiOu()
{
int a=Pow(,n*-);
int b=;
for(int i=r-;i>=;i-=) ADD(b,get_C(n<<,i));
a-=b;
if(a<) a+=b;
printf("%d",a);
} int get_inv(int x)
{
if(inv[x]!=-) return inv[x];
inv[x]=Pow(fac[x],p-);
return inv[x];
} void Cal()
{
int m=n*k;
fac[]=;
for(int i=;i<=m;++i) fac[i]=1LL*fac[i-]*i%p;
memset(inv,-,sizeof(inv));
inv[]=;
int h=r;
int ans=;
int tmp;
for(int i=; h<=m;++i,h+=k)
{
tmp=fac[m];
tmp=1LL*tmp*get_inv(h)%p*get_inv(m-h)%p;
ADD(ans,tmp);
}
printf("%d",ans);
} int main()
{
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%d%d%d%d",&n,&p,&k,&r);
if(n<= && k<=) YangHui();
else if(p==) Yu();
else if(k==) PreSum();
else if(k==) JiOu();
else Cal();
return ;
}
80分暴力
脑抽错误:
C(n,m)一定是偶数,但 对p 取模之后不能保证是偶数
考试的时候没考虑这个 ,直接/2 丢了10分,~~~~(>_<)~~~~

bzoj千题计划263:bzoj4870: [六省联考2017]组合数问题的更多相关文章
- [BZOJ4870][六省联考2017]组合数问题(组合数动规)
4870: [Shoi2017]组合数问题 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 748 Solved: 398[Submit][Statu ...
- BZOJ4870 [六省联考2017] 组合数问题 【快速幂】
题目分析: 构造f[nk][r]表示题目中要求的东西.容易发现递推公式f[nk][r]=f[nk-1][r]+f[nk-1][(r-1)%k].矩阵快速幂可以优化,时间复杂度O(k^3logn). 代 ...
- P3746 [六省联考2017]组合数问题
P3746 [六省联考2017]组合数问题 \(dp_{i,j}\)表示前\(i\)个物品,取的物品模\(k\)等于\(r\),则\(dp_{i,j}=dp_{i-1,(j-1+k)\%k}+dp_{ ...
- [六省联考2017]组合数问题 (矩阵优化$dp$)
题目链接 Solution 矩阵优化 \(dp\). 题中给出的式子的意思就是: 求 nk 个物品中选出 mod k 为 r 的个数的物品的方案数. 考虑朴素 \(dp\) ,定义状态 \(f[i][ ...
- 洛谷P3746 [六省联考2017]组合数问题
题目描述 组合数 C_n^mCnm 表示的是从 n 个互不相同的物品中选出 m 个物品的方案数.举个例子,从 (1;2;3) 三个物品中选择两个物品可以有 (1;2);(1;3);(2;3) 这三种 ...
- P3746 【[六省联考2017]组合数问题】
题目是要我们求出如下柿子: \[\sum_{i=0}^{n}C_{nk}^{ik+r}\] 考虑k和r非常小,我们能不能从这里切入呢? 如果你注意到,所有组合数上方的数\(\%k==r\),那么是不是 ...
- 洛谷$P$3746 [六省联考2017]组合数问题 $dp$+矩乘+组合数学
正解:$dp$+矩乘+组合数学 解题报告: 传送门! 首先不难发现这个什么鬼无穷就是个纸老虎趴,,,最多在$\binom{n\cdot k+r}{n\cdot k}$的时候就已经是0了后面显然不用做下 ...
- 六省联考2017 Day1
目录 2018.3.18 Test T1 BZOJ.4868.[六省联考2017]期末考试 T2 T3 BZOJ.4870.[六省联考2017]组合数问题(DP 矩阵快速幂) 总结 考试代码 T1 T ...
- 【BZOJ4873】[六省联考2017]寿司餐厅(网络流)
[BZOJ4873][六省联考2017]寿司餐厅(网络流) 题面 BZOJ 洛谷 题解 很有意思的题目 首先看到答案的计算方法,就很明显的感觉到是一个最大权闭合子图. 然后只需要考虑怎么构图就行了. ...
随机推荐
- Spring学习(十九)----- Spring与WEB容器整合
首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 filter 写在 listener 的前面而会先加载 filter.最终得出的结论是:listener -> ...
- vsftp在防火墙开启需要开放的端口
1.开放tcp端口 firewall-cmd --zone=public --add-port=20/tcp --permanent firewall-cmd --zone=public --add- ...
- 自动化部署-Jenkins+SVN+MSBuild 一些补充
1.ftp的使用 系统管理->插件管理 安装插件Publish Over FTP 系统管理->系统设置 配置ftp参数 如下图 进入任务配置,添加构建后操作 在使用过程中还遇到一个本地防火 ...
- yocto-sumo源码解析(三):oe-setup-builddir
该脚本的主要功能就是创建构建目录并准备一些配置文件,比如conf/local.conf,conf/bblayer.conf 1. 检测BUILDDIR环境变量是否设置好(在本系列分享第二节已经知道:B ...
- PAT甲题题解-1053. Path of Equal Weight (30)-dfs
由于最后输出的路径排序是降序输出,相当于dfs的时候应该先遍历w最大的子节点. 链式前向星的遍历是从最后add的子节点开始,最后添加的应该是w最大的子节点, 因此建树的时候先对child按w从小到大排 ...
- [JSP] c:forEach 如何输出序号
关键在于<c:forEach>的varStatus属性,具体代码如下: <table width="500" border="0" cells ...
- (第三周)使用visual studio 2015进行单元测试
Microsoft visual studio是目前最流行的windows平台应用程序的集成开发环境.最新版本为 Visual Studio 2015 .Visual Studio 2015 包含许多 ...
- Visual Studio 2013安装及简单的单元测试
Visual Studio 2013安装部分首先到观望下载了英文版和简体中文的语言包.但是更新语言包时总是失败,安装vs需要等待的时间也很大.后来重新装了一遍系统(这个卸载也很麻烦),从其他网站下了中 ...
- Linux dd命令制作U盘启动盘
linux下的dd命令来自于coreutils:http://www.gnu.org/software/coreutils/ https://jingyan.baidu.com/article/d45 ...
- wordApp.Documents.Open 未将对象引用实例
wordApp.Documents.Open (.........),当我打开的是.docx,能正常打开当是.doc时,却返回空置,显示失败,未能找到文件.......,但其实文件都在 解决方案 WO ...