zoukankan      html  css  js  c++  java
  • AGC040F Two Pieces

    AGC040F Two Pieces

    Description

    有两个棋子初始点都在坐标 (0) ,两个棋子之间没有区别,总共要进行 (n) 次操作,每次操作是如下操作其中之一:

    • 选择一个棋子向前移动一步。
    • 选择位置较后的那个棋子,直接移动到位置较前的那个棋子的位置。

    (n) 次操作后两个棋子分别在位置 A,B 的方案数,对 (998244353) 取模,两种方案是相同的,当且仅当两个棋子在每一步的坐标都是相同的(注意不是每一步的操作都相同)。(Ale Ble nle 10^7)

    Solution

    此题最难处理的无疑是对方案相同的定义:两个棋子在每一步的坐标都是相同的。对此,令最终走到 A,B 位置的棋子分别为 a,b,从始至终一直让 a 棋子在 b 的后面(否则一定与一个满足这一条件的走法等价)。

    于是可以用二元组 ((x,d)) 来表示当前的状态,(x) 表示 b 棋子的位置,(d) 表示 a 棋子与 b 棋子的状态,那么原问题等于有以下三种操作:

    • (x)(d) 同时加 (1)
    • (d--),但要求 (dge 2),如果 (d=1) 那么这个操作与传送没有区别,因此我们不妨认为这个操作必须满足 (dge 2)
    • (d=0)

    如果只有 (1,2) 两种操作,那么这等价于在二维平面上向右上走和向右走,要求除了第一步之外不能走到 (x) 轴及以下。设最终从 ((0,0)) 走到 ((x,y)),那么根据翻折法有答案 (=dbinom{x+y-1}{y}-dbinom{x+y-1}{x})

    (3) 操作相当于在二维平面上向下走到 (x) 轴上。因此可以发现 (1) 操作执行了恰好 (B) 次,然后枚举 (2) 操作执行的次数 (k),然后考虑在操作序列中插入剩下 (s=n-B-k)(3) 操作。

    设进行第 (i) 次操作后 (d)(d_i),如果在 (i) 后插入一个 (3) 操作,就等于将图象向下移动 (d_i) ,也就要求不存在 (j>i,d_j<d_i) 。于是不妨这 (s) 个操作分别插入在 (c_1,c_2,dots c_s) 操作之后,则相当于将图象下降了 (max_{i=1}^{s}d_{c_i})。因为我们要求最终图象下降了 (B-k-(B-A)=A-k) 个单位,于是必须有 (d_{c_s}=A-k),并且必须是最后一个 (d_i=A-k)(i)。那么此时 (c_1,c_2,dots c_{s-1}) 就可以在 (0,1,dots,A-k) 的最后一次出现位置中任选一个插入即可,这可以用插板法得到方案数为 (dbinom{s+A-k}{A-k})。于是问题在 (mathcal O(n)) 的时间内得到了解决,注意特判 (n-B-k=0) 的情况。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e7+10,mod=998244353;
    inline int ksm(int x,int y){
    	int ret=1;
    	for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) ret=1ll*ret*x%mod;
    	return ret;
    }
    int n,fac[N],inv[N],a,b;
    inline void init(int n){
    	fac[0]=1;
    	for(int i=1;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
    	inv[n]=ksm(fac[n],mod-2);
    	for(int i=n-1;i>=0;--i) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    }
    inline int binom(int x,int y){if(x<y||y<0) return 0;return 1ll*fac[x]*inv[y]%mod*inv[x-y]%mod;}
    inline int dec(int x,int y){return (x-y<0)?x-y+mod:x-y;}
    inline void inc(int &x,int y){x=(x+y>=mod)?x+y-mod:x+y;}
    int main(){
    	scanf("%d%d%d",&n,&a,&b);
    	init(n<<1);
    	int ans=0;
    	for(int k=0;k<=a&&k<=n-b;++k){
    		int x=dec(binom(b+k-1,k),binom(b+k-1,b));
    		if(!b) x=1;
    		if(k==a) inc(ans,x);
    		else ans=(ans+1ll*x*binom(n-b-k-1+a-k,a-k))%mod;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    基于springboot1.5.9整合shiro时出现静态文件找不到的问题
    基于springboot多模块项目使用maven命令打成war包放到服务器上运行的问题
    关于使用map存放数据乱序”问题“
    springboot1.5.9整合websocket实现实时显示的小demo
    SpringBoot1.5.10.RELEASE配置mybatis的逆向工程
    SpringBoot1.5.10.RELEASE整合druid时,在druid monitor界面出现(*) property for user to setup
    SpringBoot1.5.10.RELEASE整合druid
    SpringBoot1.5.10.RELEASE项目如何在tomcat容器中运行
    JS学习-01
    List,Set,Map在java.util包下都是接口 List有两个实现类:ArrayList和LinkedList Set有两个实现类:HashSet和LinkedHashSet AbstractSet实现了Set
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/15483478.html
Copyright © 2011-2022 走看看