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]组合数问题的更多相关文章

  1. [BZOJ4870][六省联考2017]组合数问题(组合数动规)

    4870: [Shoi2017]组合数问题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 748  Solved: 398[Submit][Statu ...

  2. BZOJ4870 [六省联考2017] 组合数问题 【快速幂】

    题目分析: 构造f[nk][r]表示题目中要求的东西.容易发现递推公式f[nk][r]=f[nk-1][r]+f[nk-1][(r-1)%k].矩阵快速幂可以优化,时间复杂度O(k^3logn). 代 ...

  3. P3746 [六省联考2017]组合数问题

    P3746 [六省联考2017]组合数问题 \(dp_{i,j}\)表示前\(i\)个物品,取的物品模\(k\)等于\(r\),则\(dp_{i,j}=dp_{i-1,(j-1+k)\%k}+dp_{ ...

  4. [六省联考2017]组合数问题 (矩阵优化$dp$)

    题目链接 Solution 矩阵优化 \(dp\). 题中给出的式子的意思就是: 求 nk 个物品中选出 mod k 为 r 的个数的物品的方案数. 考虑朴素 \(dp\) ,定义状态 \(f[i][ ...

  5. 洛谷P3746 [六省联考2017]组合数问题

    题目描述 组合数 C_n^mCnm​ 表示的是从 n 个互不相同的物品中选出 m 个物品的方案数.举个例子,从 (1;2;3) 三个物品中选择两个物品可以有 (1;2);(1;3);(2;3) 这三种 ...

  6. P3746 【[六省联考2017]组合数问题】

    题目是要我们求出如下柿子: \[\sum_{i=0}^{n}C_{nk}^{ik+r}\] 考虑k和r非常小,我们能不能从这里切入呢? 如果你注意到,所有组合数上方的数\(\%k==r\),那么是不是 ...

  7. 洛谷$P$3746 [六省联考2017]组合数问题 $dp$+矩乘+组合数学

    正解:$dp$+矩乘+组合数学 解题报告: 传送门! 首先不难发现这个什么鬼无穷就是个纸老虎趴,,,最多在$\binom{n\cdot k+r}{n\cdot k}$的时候就已经是0了后面显然不用做下 ...

  8. 六省联考2017 Day1

    目录 2018.3.18 Test T1 BZOJ.4868.[六省联考2017]期末考试 T2 T3 BZOJ.4870.[六省联考2017]组合数问题(DP 矩阵快速幂) 总结 考试代码 T1 T ...

  9. 【BZOJ4873】[六省联考2017]寿司餐厅(网络流)

    [BZOJ4873][六省联考2017]寿司餐厅(网络流) 题面 BZOJ 洛谷 题解 很有意思的题目 首先看到答案的计算方法,就很明显的感觉到是一个最大权闭合子图. 然后只需要考虑怎么构图就行了. ...

随机推荐

  1. cbuild-一个创建和管理C++项目的工具

    cbuild-一个创建和管理C++项目的工具 介绍: 这是个人开发的一个管理C++项目的工具,用shell脚本编写. 可能会不定期更新,也欢迎大家一起完善. 当前开发版本0.5.各版本功能如下: ve ...

  2. cocos2d-x学习之路(一)——安装cocos2d-x

    这两天想从pygame和SDL换到cocos2d-x上(主要还是为了跨平台开发),所以这里先来看看如何安装cocos2d-x. 首先到官网去下载cocos2d-x:传送门 点击上方菜单栏的Produc ...

  3. PAT甲题题解-1121. Damn Single (25)-水题

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789787.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  4. 第三次Scrum meeting

    第三次Scrum meeting 会议主要内容: 测试方面:确定测试的各个环节以及测试的相关要求,完成初步的功能测试.同时在测试时仔细记录相应错误信息,并进行备注. 沟通方面:同Dream团队(学霸前 ...

  5. 20135327郭皓--Linux内核分析第五周 扒开系统调用的三层皮(下)

    Linux内核分析第五周 扒开系统调用的三层皮(下) 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/U ...

  6. 关于github的使用心得

    https://github.com/JavaLizheng/test git常用命令: git config :配置git git add:更新working directory中的文件至stagi ...

  7. [Docker基础]如何清除不用的资源

    Docker - How to cleanup resources 有时你可能需要清理Docker中不用的资源,特别是在学习Docker过程中创建的镜像.容器.网络.存储卷等. delete volu ...

  8. PAT乙级(Basic Level)练习题-NowCoder数列总结

    题目描述 NowCoder最近在研究一个数列: F(0) = 7 F(1) = 11 F(n) = F(n-1) + F(n-2) (n≥2) 他称之为NowCoder数列.请你帮忙确认一下数列中第n ...

  9. JavaScript ES6中export及export default的区别以及import的用法

    本文原创地址链接:http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632,未经博主允许不得转载. 相信很多人都使用过export.e ...

  10. [转帖]kubeadm 实现细节

    kubeadm 实现细节 http://docs.kubernetes.org.cn/829.html 1 核心设计原则 2 常量和众所周知的值和路径 3 kubeadm init 工作流程内部设计 ...