[数学][dp] Jzoj P4236 登山

Description

恶梦是一个登山爱好者,今天他来到了黄山。
俗话说的好,不走回头路。所以在黄山,你只能往前走,或者往上走。并且很显然的是,当你走到山脊的时候,你不能够往上走,你只能往前走一步再往上走。
抽象一点而言就是,你可以把黄山视为一个N * N格点图,恶梦从(0,0)开始出发,要走到(N,N)。当他走到位置(x,y)的时候,它可以往(x + 1,y),或(x,y+1)走。
并且当他走到(x,x)的时候,由于他已经处在了山脊上,所以他不能够往(x,x+1)方向上走。
当恶梦兴致勃勃准备开始爬山的时候,他的同伴告诉他,黄山由于年久失修,有一些位置出现了大坑,不能走。恶梦觉得更刺激了,但他想先知道他能有多少种方式走到黄山顶。
由于这个数字很大,所以你只需要将答案对10^9 + 7取模输出即可。

Input

第一行包括两个整数N,C,分别表示你可以把黄山视作一个N * N的格点图,并且黄山上面有C个位置出现了大坑。
接下来的C行,每行包括两个整数X,Y,表示X,Y这个位置不能走。保证X>=Y,也就是说(X,Y)必然在山上。
保证这C个点互不相同。

Output

输出只有一个整数Ans,表示恶梦爬上山顶的路径数对10^9+7取模的值。

Sample Input

输入1:5 25 01 1输入2:7 46 55 32 17 1

Sample Output

输出1:27输出2:34

Data Constraint

对于30%的数据,保证N<=5000
对于另外20%的数据,保证C=0
对于另外20%的数据,保证C=1
对于100%的数据,保证N<=100000,C<=1000
保证对于(0,0),(N,N)不存在障碍点。

题解

  • 题目大意:给定c个不能走的点,问从(0,0)到(n,n)不经过不能走的点和y>x的点的路径数量
  • 首先30%的数据,很容易直接n^2dp就好了f[i][j]=f[i-1][j]+f[i][j-1]
  • 考虑一下反过来做,ans=全部的路径-不合法的路径
  • 显然我们可知道从(0,0)到(x,y)的无限制的路径数=C(x+y,x)
  • 那么现在就来考虑一下不合法的路径数
  • 先考虑一下没有山脊限制的情况,设f[i]表示走到第i个路障的方案数(不经过其他的路障)
  • 那么f[i]可以从其他路障的f[j]转移容斥过来得到,就是在经过第j个路障时容斥掉不合法的路径数
  • 再考虑一下有山脊的限制,对于从(a,b)要走到(c,d),那么不碰到对称轴的方案数=所有走到(c,d)的方案数-所有走到(c,d)关于对称轴对称的对称点的方案数
  • 就按照上面的方法做就好了,完结(撒花)

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #define ll long long
 5 using namespace std;
 6 const int N=100010,mo=1e9+7;
 7 int n,c;
 8 ll f[N],g[N],fac[2*N],ny[2*N],r;
 9 struct edge { ll x,y; }a[N];
10 ll ksm(ll a,ll b) { for (r=1;b;b>>=1,a=a*a%mo) if (b&1) r=r*a%mo; return r; }
11 ll C(int b,int a)
12 {
13     if (a==0||a==b) return 1;
14     return ((fac[b]*ny[a])%mo*ny[b-a])%mo;
15 }
16 bool cmp(edge a,edge b) { return a.x<b.x||a.x==b.x&&a.y<b.y; }
17 ll calc(int i,int j)
18 {
19     int x=a[j].x-a[i].x,y=a[j].y-a[i].y;
20     if (x<0||y<0) return 0;
21     if (a[j].y-1-a[i].x<0||a[j].x+1-a[i].y<0) return C(x+y,x);
22     return (C(x+y,x)-C(x+y,a[j].y-1-a[i].x)+mo)%mo;
23 }
24 int main()
25 {
26     scanf("%d%d",&n,&c);
27     for (int i=1;i<=c;i++) scanf("%d%d",&a[i].x,&a[i].y);
28     fac[1]=ny[1]=1; for (int i=2;i<=n*2;i++) fac[i]=(fac[i-1]*i)%mo,ny[i]=ksm(fac[i],mo-2);
29     a[c+1].x=n,a[c+1].y=n,sort(a,a+c+1,cmp);
30     for (int i=1;i<=c+1;i++)
31     {
32         for (int j=1;j<i;j++) (g[i]+=f[j]*calc(j,i)%mo)%=mo;
33         f[i]=(calc(0,i)-g[i]+mo)%mo;
34     }
35     printf("%lld",f[c+1]);
36 }

原文地址:https://www.cnblogs.com/Comfortable/p/10331482.html

时间: 2024-08-29 13:26:22

[数学][dp] Jzoj P4236 登山的相关文章

数学+dp HDOJ 5317 RGCDQ

题目传送门 1 /* 2 题意:给一个区间,问任意两个数的素数因子的GCD最大 3 数学+dp:预处理出f[i],发现f[i] <= 7,那么用dp[i][j] 记录前i个f[]个数为j的数有几个, 4 dp[r][j] - dp[l-1][j]表示区间内j的个数,情况不多,分类讨论一下 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #include <vecto

数学+DP Codeforces Round #304 (Div. 2) D. Soldier and Number Game

题目传送门 1 /* 2 题意:这题就是求b+1到a的因子个数和. 3 数学+DP:a[i]保存i的最小因子,dp[i] = dp[i/a[i]] +1;再来一个前缀和 4 */ 5 /************************************************ 6 Author :Running_Time 7 Created Time :2015-8-1 14:08:34 8 File Name :B.cpp 9 ******************************

HDU 1041 Computer Transformation 数学DP题解

本题假设编程是使用DP思想直接打表就能够了. 假设是找规律就须要数学思维了. 规律就是看这些连续的0是从哪里来的. 我找到的规律是:1经过两次裂变之后就会产生一个00: 00经过两次裂变之后也会产生新的00:故此须要记录好1和00出现的次数就能够递推出后面的00出现的数据了. 公式就是tbl00[i] = tbl00[i-2] + tbl1[i-2]; 当中tbl00是记录00出现的次数,tbl1是出现1出现的次数. 公式事实上是能够化简的,只是我懒得化简了.这种公式非常清楚了. 只是因为这种数

hdu - 4972 - A simple dynamic programming problem(数学 + dp)

题意:NBA比赛,双方共N次进球(N<=100000),无论哪方,进一个球(得分只可能为1,2,3),就记录一次(记两队分数差的绝对值),问最后两队的比分有多少种. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4972 -->>知道最后的比分差k,怎么求得比分呢?设分数较低的一方的最后分数为x,则另一方的最后分数为x + k,设双方最后总分和为S,则x  = (S - k) / 2,可得双方的比分..所以,只要知道最后双方的总分和,就可以

[容斥原理][dp]JZOJ P3056 数字

[问题描述] 一个数字被称为好数字当他满足下列条件: 1. 它有2*n个数位,n是正整数(允许有前导0) 2. 构成它的每个数字都在给定的数字集合S中. 3. 它前n位之和与后n位之和相等或者它奇数位之和与偶数位之和相等 例如对于n=2,S={1,2},合法的好数字有1111,1122,1212,1221,2112,2121,2211,2222这样8种. 已知n,求合法的好数字的个数mod 999983. Input 第一行一个数n. 接下来一个长度不超过10的字符串,表示给定的数字集合. Ou

[DP]JZOJ 5907 轻功

Description 题目背景:尊者神高达进入了基三的世界,作为一个 mmorpg 做任务是必不可少的,然而跑地图却令人十分不爽.好在基三可以使用轻功,但是尊者神高达有些手残,他决定用梅花桩练习轻功.题目描述:一共有 n 个木桩,要求从起点(0)开始,经过所有梅花桩,恰好到达终点 n,尊者神高达一共会 k 种门派的轻功,不同门派的轻功经过的梅花桩数不同,花费时间也不同.但是尊者神高达一次只能使用一种轻功,当他使用别的门派的轻功时,需要花费 W 秒切换(开始时可以是任意门派,不需要更换时间).由

[概率期望DP]JZOJ 4212 我想大声告诉你

Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一些人,小R 自然也参加了.这个游戏有n 个人参加,每一轮随机选出一个还没有出局的人x,接着x 会出局.x 在出局之后剩下的人会受到一次攻击,每一个人在遭到攻击之后会有p 的概率出局.(注意遭到攻击出局的人是不能攻击剩下的人的)在所有人都出局之后,遭受攻击次数等于特定值的人能够成为胜者.所以现在小R 想要知道对于每一个0 <= k < n,自己恰好在遭受k 次攻击之后出局的概率是多

[Tarjan][并查集][dp] Jzoj P4253 QYQ在艾泽拉斯

Description 在艾泽拉斯的无尽之海里,有着一群不为人知的由各个种族的冒险者统治的岛屿,这些岛屿都很庞大,足以在上面建造许多的城市,城市之间有一些单向道路连接.有一天,QYQ无意中发现了这些岛屿,并且发现在每个城市的地下都或多或少埋藏着一些装备.金币.宝物……可是正当QYQ兴奋不已打算全部把它们拿走时,他却惊奇的发现你的魔法在这里被限制住了,唯一可用的技能就是闪现,而且魔法只够他使用K次这个技能了,每次使用这个技能QYQ只能从一个岛屿上闪现到另外一个岛屿上.每一个岛屿只能登上一次,QYQ

HDU - 2050 - 折线分割平面(数学 + dp)

题意: 我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目.比如,一条折线可以将平面分成两部分,两条折线最多可以将平面分成7部分 思路: 记住结论... 平面分割 n(n+1)/2+1 折现分割2n^2-n+1 封闭曲线分平面问题n^2-n+2 平面分割空间问题(n^3+5n)/6+1 dalao的推到过程:https://www.jianshu.com/p/18ed6a125e82 代码: #include<iostream> using n