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 洛谷 题解 很有意思的题目 首先看到答案的计算方法,就很明显的感觉到是一个最大权闭合子图. 然后只需要考虑怎么构图就行了. ...
随机推荐
- Repository模式与UnitOfWorks模式的运用
软件开发就像是一个江湖,而设计模式就是一本高深的秘籍每读一次.用一次.想一次都能得到新的领悟,让我们的设计技能有所提高.开始时我们可能会“为了模式而模式”,让代码变得乱78糟甚至难以让人理解,但随着设 ...
- 移动webapp的那些令你头疼的事
bug持续更新中... 测试浏览器 Chrome: 61.0.3163.73 Safari: 10.0(IOS 10.3.3) Github: webapp-bugs 1. IOS overflow: ...
- DMS专线联通外网测试
配置 CE Ping PE: “本地链接”-->属性-->"Internet 协议版本4(TCP/IPv4)",选择“使用下面的IP”,填写“172.16.10.21” ...
- Appium+Python3+ Android入门
前言: Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用. 一.环境配置 1.安装Node.js https://nodejs.o ...
- hadoop balance工具平衡集群dfs存储及遇到异常Got error, status message Not able to receive block 1073959989 from /192.168.1.37:3004 because threads quota is exceeded
hadoop集群某个节点dfs存储比其他节点存储高时,一般会使用hadoop提供的balance(start-balancer.sh -threshold 10 )工具来移动高存储节点上的块到低存储节 ...
- 猎豹CEO傅盛:95%的人碌碌无为,只是不懂这一点!
我一直在思索,怎么才能让一家公司更快地成长?一个人怎么才能从一群人的竞争当中脱颖而出? 1. 人的四种认知状态 最近我看了一幅图,我在其上加了一个数字注脚. 这是一个人认知的四种状态——“不知道自 ...
- LeetCode 504. Base 7 (C++)
题目: Given an integer, return its base 7 string representation. Example 1: Input: 100 Output: "2 ...
- 对比网络模拟器软件——Cisco Packet Tracer、华为eNSP、H3C Cloud Lab
1.软件介绍 1.1 Cisco Packet Tracer Cisco Packet Tracer(以下简称PT)是一款由思科公司开发的,为网络课程的初学者提供辅助教学的实验模拟器.使用者可以在该模 ...
- PAT 1043 输出PATest
https://pintia.cn/problem-sets/994805260223102976/problems/994805280074743808 给定一个长度不超过10000的.仅由英文字母 ...
- Linux命令学习chroot和chmode
chroot:chang root http://man.linuxde.net/chroot https://baike.baidu.com/item/chroot 1.限制被CHROOT的使用者所 ...