ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 洛谷 P1641 【[SCOI2010]生成字符串】

2022-09-10 03:01:45  阅读:176  来源: 互联网

标签:洛谷 int 题解 ll 个数 P1641 return MOD define


\(P1641 [SCOI2010]\)生成字符串


前置知识

    组合数、坐标轴。

题目描述

    以\(n\)个\(1\)和\(m\)个\(0\)组成字符串,求出满足条件「在任意的前\(k\)个字符中,\(1\)的个数不能少于\(0\)的个数」的字符串数量。

解题思路

    考虑到题目要求的条件「\(1\)的个数不少于\(0\)的个数」可以转化为坐标轴内点的横纵坐标。
    举例说明:

front

    第一步:建系。将\(x\)轴设为\(m + n\),y轴设为\(m - n\),方案数则可以表示为从点\((0,0)\)移动到点\((n + m,n - m)\)的折线,每增加一个\(1\)或\(0\)代表当前点向\(x\)轴正半轴移动一单位长度,选择\(1\)代表向y轴正半轴移动一单位长度,选择\(0\)代表向\(y\)轴负半轴移动一单位长度。易得方案总数即为\(C(n+m,n)\)。
     因为\(1\)的个数始终不少于\(0\)的个数,所以折线需保持在第一象限。

    第二步:排除不合法情况:\(1\)的个数少于\(0\)的个数,即折线在第四象限。
    我们考虑将在到达\(y = -1\)以前的部分全部沿\(y = -1\)的直线作对称,如下图所示。
bottom
    折线的新起点变为\((0,-2)\),总次数还是\(n + m\),但上升次数比下降次数多一次,方案数为\(C(n+m,m-1)\)。

    第三步:综合前两步的推导,得出式子:\(Ans = C(n + m,n) - C(n + m,m - 1)\)。

注意事项

    \(1\).注意取模。
    \(2\).数据范围过大,先预处理逆元,再套用公式求出组合数。

参考程序

#include<bits/stdc++.h>
#define re register
#define il inline
#define ll long long
#define MAXN 1000005
#define MAXM 1000005
#define MOD  20100403
#define rep(i,a,b)  for(re int i = a;i <= b;i ++)
#define drep(i,a,b) for(re int i = a;i >= b;i --)
#define Rep(i,a,b)  for(re int i = a;i < b;i ++)
#define Drep(i,a,b) for(re int i = a;i > b;i --)
#define fin(a)  freopen(#a".in","r",stdin)
#define fout(a) freopen(#a".out","w",stdout)

using namespace std;

il ll read(){
	ll x = 0;
	char ch = 0;
	while(!isdigit(ch)){
		ch = getchar();
	}
	while(isdigit(ch)){
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	return x;
}

il void write(ll x){
	if(x > 9){
		write(x / 10);
	}
	putchar(x % 10 + '0');
}

il ll Pow(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b & 1)
			ans = ans * a % MOD;
		a = a * a % MOD;
        b >>= 1;
	}
	return ans % MOD;
}

il ll C(ll n,ll m){
	if(m > n)
		return 0;
	if(m > n - m)
		m = n - m;
	
	ll s1 = 1,s2 = 1;
	Rep(i,0,m){
		s1 = s1 * (n - i) % MOD;
		s2 = s2 * (i + 1) % MOD;
	}
	return s1 * Pow(s2,MOD - 2) % MOD;
}

il ll Lucas(int n,int m){
	if(!m)
		return 1;
	return C(n % MOD,m % MOD) * Lucas(n / MOD,m / MOD) % MOD;
}



int main(){
    #ifndef ONLINE_JUDGE
    fin(1641);
    fout(1641);
    #endif
    
	int n = read(),m = read();
	write((Lucas(n + m,n) % MOD - Lucas(n + m,m - 1) % MOD + MOD) % MOD);
	
	return 0;
}

标签:洛谷,int,题解,ll,个数,P1641,return,MOD,define
来源: https://www.cnblogs.com/StudyingVeyron-MUST/p/16675895.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有