[VIJOS2055][SDOI2019]移动金币:DP+组合数学
分析
显然可以转化为阶梯nim。
于是问题转化为了对于所有\(i \in [0,n-m]\),求长度为\(\lfloor\frac{m+1}{2}\rfloor\),和为\(i\),异或和非\(0\)的非负整数序列的个数。
直接DP看似不太可行,然而UOJ群的dalao们告诉博主可以按位DP。
令\(f[i][j][0/1]\)表示考虑了后\(i\)位,当前的和为\(j\),后\(i\)位的异或和是否为\(0\)的方案数,转移时枚举当前位有多少个\(1\),类似数位DP那样就好。
最后用隔板法统计答案即可。
记搜的话直接记搜可能过不去,加些剪枝就好了。
代码
#include <bits/stdc++.h>
#define rin(i,a,b) for(int i=(a);i<=(b);++i)
#define irin(i,a,b) for(int i=(a);i>=(b);--i)
#define trav(i,a) for(int i=head[a];i;i=e[i].nxt)
#define Size(a) (int)a.size()
#define pb push_back
#define mkpr std::make_pair
#define fi first
#define se second
#define lowbit(a) ((a)&(-(a)))
typedef long long LL;
using std::cerr;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int MOD=1e9+9;
const int MAXN=150005;
int n,m,cnt;
int fac[MAXN+50],invf[MAXN+50];
int f[20][MAXN][2];
inline int qpow(int x,int y){
int ret=1,tt=x%MOD;
while(y){
if(y&1)ret=1ll*ret*tt%MOD;
tt=1ll*tt*tt%MOD;
y>>=1;
}
return ret;
}
inline int binom(int n,int m){
if(n<0||m<0||n<m)return 0;
return 1ll*fac[n]*invf[n-m]%MOD*invf[m]%MOD;
}
int dfs(int pos,int sum,int have1){
if(sum&((1<<pos)-1))return 0;
if(pos>17){
if(sum==0&&have1)return 1;
else return 0;
}
if(f[pos][sum][have1]!=-1)return f[pos][sum][have1];
int ret=0;
rin(i,0,cnt){
if((1ll<<pos)*i>sum)break;
ret=(ret+1ll*dfs(pos+1,sum-(1ll<<pos)*i,have1|(i&1))*binom(cnt,i))%MOD;
}
return f[pos][sum][have1]=ret;
}
void init(){
fac[0]=1;
rin(i,1,n+m)fac[i]=1ll*fac[i-1]*i%MOD;
invf[n+m]=qpow(fac[n+m],MOD-2);
irin(i,n+m-1,0)invf[i]=1ll*invf[i+1]*(i+1)%MOD;
}
int main(){
memset(f,-1,sizeof f);
n=read(),m=read();init();
cnt=(m+1)/2;
int ans=0,box=(m&1)==0?cnt+1:cnt;
rin(i,0,n-m){
int rem=n-m-i;
ans=(ans+1ll*dfs(0,i,0)*binom(rem+box-1,box-1))%MOD;
}
printf("%d\n",ans);
return 0;
}
[VIJOS2055][SDOI2019]移动金币:DP+组合数学的更多相关文章
- CF_229E_Gift_概率DP+组合数学
CF_229E_Gift_概率DP+组合数学 题目描述: 很久很久以前,一位老人和他的妻子住在蔚蓝的海边.有一天,这位老人前去捕鱼,他捉到了一条活着的金鱼.鱼说:“噢,老渔人!我祈求你放我回到海里,这 ...
- [多校联考2019(Round 5 T3)]青青草原的表彰大会(dp+组合数学)
[多校联考2019(Round 5)]青青草原的表彰大会(dp+组合数学) 题面 青青草原上有n 只羊,他们聚集在包包大人的家里,举办一年一度的表彰大会,在这次的表彰大会中,包包大人让羊们按自己的贡献 ...
- [Codeforces722E] Research Rover (dp+组合数学)
[Codeforces722E] Research Rover (dp+组合数学) 题面 给出一个N*M的方格阵,从(1,1)出发,到(N,M)结束,从(x,y)只能走到(x+1,y)或(x,y+1) ...
- # [SDOI2019]移动金币 阶梯博弈 dp
[SDOI移动金币 链接 vijos 思路 阶梯博弈,dp统计. 参见wxyww 代码 #include <bits/stdc++.h> using namespace std; cons ...
- [SDOI2019]移动金币(博弈论+阶梯Nim+按位DP)
首先可以把问题转化一下:m堆石子,一共石子数不超过(n-m)颗,每次可以将一堆中一些石子推向前一堆,无法操作则失败,问有多少种方法使得先手必胜? 然后这个显然是个阶梯Nim,然后有这样的结论:奇数层异 ...
- P5363-[SDOI2019]移动金币【阶梯博弈,dp,组合数学】
正题 题目链接:https://www.luogu.com.cn/problem/P5363 题目大意 \(1\times n\)的网格上有\(m\)个硬币,两个人轮流向前移动一个硬币但是不能超过前一 ...
- CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)
问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...
- CF_402F dp+组合数学
题目链接:http://codeforces.com/problemset/problem/403/D /**算法分析: 这道题综合的考察了dp背包思想和组合数学 */ #include<bit ...
- 【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
3294: [Cqoi2011]放棋子 Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数 ...
随机推荐
- HDU3336 Count the string(kmp
It is well known that AekdyCoin is good at string problems as well as number theory problems. When g ...
- stm32F429启动时钟配置
STM32f429在启动时会在startup_stm32f429_439xx.s中调用static void SetSysClock(void)函数.默认使用的是25M晶振,把系统时钟设置为180M. ...
- Alibaba开源组件-分布式流量控制框架sentinel初探
Alibaba开源组件-分布式流量控制框架sentinel初探 2018年12月09日 18:23:11 SuperPurse 阅读数 1965更多 分类专栏: J2EE 版权声明:本文为博主原创 ...
- java -cp 执行jar包里的某个类
当我们需要测试某个功能时,需要在linux环境下执行某个类的main方法来测试 可以使用java -cp xxx.jar com.MyClass来执行某个类 java -cp test.jar:lib ...
- 机器学习-正则化(岭回归、lasso)和前向逐步回归
机器学习-正则化(岭回归.lasso)和前向逐步回归 本文代码均来自于<机器学习实战> 这三种要处理的是同样的问题,也就是数据的特征数量大于样本数量的情况.这个时候会出现矩阵不可逆的情况, ...
- 关于redis的几件小事(十)redis cluster模式
redis cluster是redis提供的集群模式. 1.redis cluster的架构 ①可以有多个master node,每个master node 都可以挂载多个slave node. ②读 ...
- Linux之常用脚本
1) #检查php Money 队列脚本是否启动 php_count=`ps -ef | grep Money | grep -v "grep" | wc -l` ];then e ...
- bilibili小程序项目总结
1.关于mock的使用 第一步:先到Mock官网(http://mockjs.com/)上面熟悉一下基本用法 第一步:具体使用实例: 下载wxMock.js和mock.js文件 下载地址:https: ...
- 使用 java 创建你的第一个区块链(第二部分)
本系列教程的目的是帮助您了解如何开发区块链技术. 在这第二个教程中,我们将: 创建一个简单的钱包: 使用我们的区块链发送已签名的交易: 感觉更酷. 以上这些将使我们拥有自己的加密货币! 从上一个教程开 ...
- js 简单实现隐藏和显示
<html> <head> <meta charset="gb2312"> <title>隐藏和显示</title> & ...