[CSP-S模拟测试]:题(DP+数学)
题目描述
出个题就好了.这就是出题人没有写题目背景的原因。
你在平面直角坐标系上。
你一开始位于$(0,0)$。
每次可以在上/下/左/右四个方向中选一个走一步。
即:从$(x,y)$走到$(x,y+1),(x,y-1),(x-1,y),(x+1,y)$四个位置中的其中一个。
允许你走的步数已经确定为$n$,现在你想走$n$步之后回到$(0,0)$。
但这太简单了,你希望知道有多少种不同的方案能够使你在n步之后回到$(0,0)$,当且仅当两种方案至少有一步走的方向不同,这两种方案被认为是不同的.
答案可能很大所以只需要输出答案对${10}^9+7$取模后的结果。
这还是太简单了,所以你给能够到达的格点加上了一些限制,一共有三种限制,加上没有限制的情况,一共有四种情况,用$0,1,2,3$标号:
$0.$没有任何限制,可以到达坐标系上所有的点。即能到达的点集为$\{ (x,y)|x,y$为整数$\}$
$1.$只允许到达x轴非负半轴上的点。即能到达的点集为$\{ (x,y)\|x$为非负数$,y=0\}$
$2.$只允许到达坐标轴上的点。即能到达的点集为$\{ (x,y)\|x=0$或$y=0\}$
$3.$只允许到达$x$轴非负半轴上的点,$y$轴非负半轴上的点以及第$1$象限的点。即能到达的点集为$\{ (x,y)\| x\geqslant 0,y\geqslant 0\}$
输入格式
一行两个整数(空格隔开)n和typ,分别表示你必须恰好走的步数和限制的种类。
typ的含义见【题目描述】
输出格式
一行一个整数ans,表示不同的方案数对${10}^9+7$取模后的结果。
样例
样例输入0:
100 0
样例输出0:
383726909
样例输入1:
100 1
样例输出1:
265470434
样例输入2:
100 2
样例输出2:
376611634
样例输入3:
100 3
样例输出3:
627595255
数据范围与提示
$10\%$的数据,$typ=0,n\leqslant 100$
$10\%$的数据,$typ=0,n\leqslant 1,000$
$ 5\%$的数据,$typ=0,n\leqslant 100,000$
$10\%$的数据,$typ=1,n\leqslant 100$
$10\%$的数据,$typ=1,n\leqslant 1,000$
$ 5\%$的数据,$typ=1,n\leqslant 100,000$
$10\%$的数据,$typ=2,n\leqslant 100$
$15\%$的数据,$typ=2,n\leqslant 1,000$
$10\%$的数据,$typ=3,n\leqslant 100$
$10\%$的数据,$typ=3,n\leqslant 1,000$
$ 5\%$的数据,$typ=3,n\leqslant 100,000$
以上$11$部分数据没有交集。
$100%$的数据,保证$n$为偶数,$2\leqslant n\leqslant 100,000$,$0\leqslant typ\leqslant 3$。
题解
一个数学和$DP$的大结合。
首先,这四问都可以用$\Theta (n^3)$的$DP$拿到部分分。
定义$dp[t][i][j]$表示$t$时刻在点$(i,j)$的方案数。
$DP$式子为:
$dp[t][i][j]=dp[t-1][i-1][j]+dp[t-1][i][j-1]+dp[t-1][i+1][j]+dp[t-1][i][j+1]$。
注意边界就好了。
期望得分:$40$分。
$typ=0$的情况,显然让我们想到了visit那道题,25分就轻松拿到了。
$typ=1$的情况,我们可以理解为向右走为进栈,想左走为出栈,那么就是求卡特兰数的第$\frac{n}{2}$项,直接用公式解决就可以了,附带一个卡特兰数的求法。
$typ=2$的情况,注意数据范围$n\leqslant 1,000$,所以我们可以考虑$\Theta (n^2)$的做法,定义$dp[t][i]$表示在$t$时刻位于距离原点为$i$的方案数,现在我们只考虑它在$x$轴上的情况,那么$DP$式子为:$dp[t][i]=dp[t-1][i-1]+dp[t-1][i+1]$,现在放回在坐标系上的情况,那么只有在原点的时候才会有四个方向向它贡献答案,那么$DP$式子只在$i=0$时发生改变,为:$dp[t][0]=4\times dp[t-1][1]$,也可以用滚动数组节省空间。注:正解为卡特兰数,在此介绍另一种做法。
$typ=3$的情况,只是在$typ=1$的情况上加一个枚举横向走的步数$i$纵向的步数即为$n-i$,需要注意的是横向的步数肯定为偶数步,那么方案数就是:$C_n^i\times catalan\frac{i}{2}\times catalan\frac{n-i}{2}$。
代码时刻
#include<bits/stdc++.h>
using namespace std;
int n,typ;
long long inv[200001],jget_C[200001];
long long dp[1001][1001];
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y%2)res=(res*x)%1000000007;
y>>=1;
x=(x*x)%1000000007;
}
return res;
}
void pre_work()
{
jget_C[0]=1; jget_C[1]=1;
for(int i=2;i<=n;i++)jget_C[i]=1LL*jget_C[i-1]*i%1000000007;
inv[0]=1; inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=1LL*(1000000007-1000000007/i)*inv[1000000007%i]%1000000007;
for(int i=1;i<=n;i++)inv[i]=1LL*inv[i]*inv[i-1]%1000000007;
}
long long get_C(int n,int m)
{
if(n<m)return 0;
if(m==0)return 1;
return (jget_C[n]%1000000007*inv[m]%1000000007*inv[n-m]%1000000007)%1000000007;
}
long long get_Catalan(int x){return get_C(2*x,x)%1000000007*qpow((long long)(x+1),1000000005)%1000000007;}
int main()
{
scanf("%d%d",&n,&typ);
pre_work();
switch(typ)
{
case 0:
{
long long ans=0;
for(int i=0;i<=n;i+=2)
ans=(ans+get_C(n,i)%1000000007*get_C(i,i/2)%1000000007*get_C(n-i,(n-i)/2)%1000000007)%1000000007;
printf("%lld",ans%1000000007);
break;
}
case 1:
{
printf("%lld",get_Catalan(n/2));
break;
}
case 2:
{
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
dp[i][0]=dp[i-1][1]*4%1000000007;
for(int j=1;j<=n/2;j++)
dp[i][j]=(dp[i-1][j-1]+dp[i-1][j+1])%1000000007;
}
printf("%lld\n",dp[n][0]);
break;
}
case 3:
{
long long ans=0;
for(int i=0;i<=n;i+=2)
ans=(ans+get_C(n,i)%1000000007*get_Catalan(i/2)%1000000007*get_Catalan((n-i)/2)%1000000007)%1000000007;
printf("%lld",ans);
break;
}
}
return 0;
}
rp++
[CSP-S模拟测试]:题(DP+数学)的更多相关文章
- [CSP-S模拟测试]:题(DP)
题目描述 由于出题人赶时间所以没办法编故事来作为背景.一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况.$\bullet 1.$两个苹 ...
- [CSP-S模拟测试]:装饰(数学)
题目传送门(内部题147) 输入格式 每个测试点第一行一个正整数$T$,表示该测试点内的数据组数. 接下来$T$行,每行三个非负整数$a,b,c$,含义如题目中所示. 输出格式 对每组数据输出一行一个 ...
- [CSP-S模拟测试]:Six(数学)
题目传送门(内部题85) 输入格式 一个正整数$N$. 输出格式 一个数表示答案对$1000000007$取模后的结果 样例 样例输入1: 样例输出1: 样例输入2: 样例输出2: 样例输入3: 样例 ...
- [CSP-S模拟测试]:chess(数学)
题目描述 $dirty$在一个棋盘上放起了棋子. 棋盘规格为$n\times m$,他希望任意一个$n\times n$的区域内都有$C$个棋子.$dirty$很快就放置好了一个满足条件的棋盘方案,但 ...
- [CSP-S模拟测试]:旅行(数学+线段树)
题目传送门(内部题12) 输入格式 第一行,一个整数$n$,代表树的点数.第二行,$n$个整数,第$i$个整数是$B_i$,描述排列$B$.接下来$n−1$行,每行两个整数$u,v$,描述一条树边$( ...
- [CSP-S模拟测试]:A(数学)
题目传送门(内部题44) 输入格式 一行四个整数,分别表示$S,T,a,b$. 输出格式 输出最小步数,数据保证有解. 样例 样例输入: 10 28 4 2 样例输出: 数据范围与提示 样例解释: 先 ...
- [CSP-S模拟测试]:最大值(数学+线段树)
题目背景 $Maxtir$最喜欢最大值. 题目传送门(内部题128) 输入格式 第$1$行输入四个正整数$n,m,q$. 第$2$至$n+1$行中,第$i+1$行输入魔法晶石$i$的三种属性$(x_i ...
- [CSP-S模拟测试]:求和(数学)
题目传送门(内部题107) 输入格式 一行五个正整数$x_1,y_1,x_2,y_2,m$ 输出格式 输出一个整数,为所求的答案对$m$取模后的结果. 样例 样例输入: 2 1 5 3 10007 样 ...
- [CSP-S模拟测试]:数列(数学)
题目传送门(内部题95) 输入格式 第一行三个整数$n,a,b$,第二行$n$个整数$x_1\sim x_n$表示数列. 输出格式 一行一个整数表示答案.无解输出$-1$. 样例 样例输入:2 2 3 ...
随机推荐
- CentOS 7.6 RPM 方式安装Oracle19c 后 使用 systemd 的方式设置开机自动启动Oracle数据库
1. 方法简介: 使用systemd 来进行 oracle数据库的启动和关闭操作. 使用的脚本为 lsnrctl和dbstart 2. 修改事项. 需要先修改一下 oracle 的启动脚本配置: vi ...
- [转帖]Oracle 使用sqlnet.ora/trigger限制/允许某IP或IP段访问指定用户
Oracle 使用sqlnet.ora/trigger限制/允许某IP或IP段访问指定用户 原创 Oracle 作者:maohaiqing0304 时间:2016-05-03 17:05:46 17 ...
- P2294 [HNOI2005]狡猾的商人(差分约束)
P2294 [HNOI2005]狡猾的商人 对于每个$(x,y,w)$,连边$(x-1,y,w),(y,x-1,-w)$,表示前$y$个月的收益比前$x-1$个月的收益大$w$ 这样题目就转化为询问图 ...
- 使用SecureCRT 8.5快速打开sftp传输文件
一般使用Windows系统上安装的SecureCRT 8.5软件远程连接Linux服务器,通常给Linux系统传输文件或者使用FTP,或者使用SFTP等其他第三方软件,有时Linux系统上还需要做其他 ...
- C++ constexpr
1.constexpr 1.const与constexpr: const: 承若不改变这个值,主要用于说明接口,这样在把变量传入函数时就不必担心变量会在函数内被改变了,编译器负责确认并执行const的 ...
- java语法糖:(1)可变长度参数以及foreach循环原理
语法糖 语法糖:是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这些语法做一些处理,开发者就可以直接方便地使用 ...
- Java第三阶段复习
Java第三阶段复习: 1. Spring 1. IOC: 定义:Inverse Of Controller:反转控制,将bean对象的创建和对象之间的关联关系的维护由原来我们自己创建.自己维护反转给 ...
- 欢迎使用Markdown编辑器
#欢迎使用Markdown编辑器 你好 ,这是我第一次使用Markdown编辑器所展示的页面.如果你想学习如何使用Markdown编辑器,可以仔细阅读这篇文章,了解一下Markdown的基本语法知识. ...
- STM32 常用词汇释义
1.AF——Alternate function 复用功能: 2.NVIC——Nested Vectored Interrupt Controller 内嵌向量中断控制器 3.ISER[8]— ...
- Linux之bash的变量
1. 变量的显示,echo echo $变量 或 echo ${变量} eg. echo $HOME 或 echo ${HOME} 2. 变量的设置 变量的设置规则: (1)变量与变 ...