CF896D Nephren Runs a Cinema

题意

售票员最开始没有纸币,每次来一个顾客可以给她一张、拿走她一张或不操作。求出不出现中途没钱给的情况 \(n\) 名顾客后剩余钱数在 \(l\sim r\) 的方案数。

思路

这是我们一道模拟赛题。

解法 1:套路组合计数。先不考虑不操作的顾客,那么就相当于是求二维平面不过一条直线到达一点的方案数。直接枚举操作顾客数,用组合数减去另外一个组合数然后乘上所有顾客中选这些顾客的方案数即可。

解法 2:暴力动态规划。每次从至多三个方向转移。

赛时我先想到第一个解法但是没想到枚举操作人数,以为不可做,于是想到了优化暴力的解法。

解法 3:解法 2 的优化。求出 \(F=(x^{-1}+1+x)^n\) ,然后 \(f(x)-f(x+2)\) 的第 \(l \sim r\) 项的和即为答案。

\((x^{-1}+1+x)\) 表示三种转移方式,但是求出来的 \(F\) 显然不是正确答案,因为会有从负数幂的贡献是应该减掉的。

那么我们就考虑减掉它,实际上和解法一相同,\(f(x)-f(x+2)\) 相当于减去了错解,那么减完之后就是答案了。

因为每次要倍长多项式,使用快速幂一样的方式卷就可以了。根据主定理,时间复杂度 \(O(n\log n)\)。

考场上有部分分,模数为 \(998244353\),那么正解只需要改成任意模数多项式乘法就行了。

代码

注意,此代码不可 AC 此题,仅在模数为 \(998244353\) 时正确。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cstdlib>
using namespace std;
inline int read(){
int x=0,w=0;char c=getchar();
while(!isdigit(c)) w|=c=='-',c=getchar();
while(isdigit(c)) x=x*10+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=2e6+10,mod=998244353,ge=3,gi=998244354/3;
inline int fpow(int a,int b){int ans=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;}
struct NTT{
int r[maxn],lim;
inline void getr(int li){lim=li;for(int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));}
inline void operator () (int *a,int type) const {
for(int i=0;i<lim;i++) if(i<r[i]) swap(a[i],a[r[i]]);
for(int mid=1;mid<lim;mid<<=1){
int rt=fpow(type==1?ge:gi,(mod-1)/(mid<<1));
for(int r=mid<<1,j=0;j<lim;j+=r){
int p=1;
for(int k=0;k<mid;k++,p=1ll*p*rt%mod){
int x=a[j+k],y=1ll*p*a[j+k+mid]%mod;
a[j+k]=(x+y)%mod,a[j+k+mid]=(x-y+mod)%mod;
}
}
}
if(type==-1) for(int p=fpow(lim,mod-2),i=0;i<lim;i++) a[i]=1ll*a[i]*p%mod;
}
}ntt;
int n;
int a[maxn],ans[maxn];
inline void work(){
n=read();read();
int Lim=4,lim=2;
a[0]=a[1]=a[2]=ans[0]=1;
int x=n,Len=3,len=1;
while(x){
static int res[maxn],tmp[maxn];
if(x&1){
for(int i=0;i<Lim;i++) res[i]=a[i];
for(int i=Lim;i<Lim+lim;i++) res[i]=0;
for(int i=0;i<lim;i++) tmp[i]=ans[i];
for(int i=lim;i<Lim+lim;i++) tmp[i]=0;
len+=Len;lim=Lim;
while(lim<len) lim<<=1;
ntt.getr(lim<<1);
ntt(res,1),ntt(tmp,1);
for(int i=0;i<lim<<1;i++) tmp[i]=1ll*res[i]*tmp[i]%mod;
ntt(tmp,-1);
for(int i=0;i<lim;i++) ans[i]=tmp[i];
}
for(int i=0;i<Lim;i++) res[i]=a[i];
for(int i=Lim;i<Lim<<1;i++) res[i]=0;
Lim<<=1;Len<<=1;
for(int i=Lim;i<Lim<<1;i++) res[i]=0;
ntt.getr(Lim<<1);
ntt(res,1);
for(int i=0;i<Lim<<1;i++) res[i]=1ll*res[i]*res[i]%mod;
ntt(res,-1);
for(int i=0;i<Lim;i++) a[i]=res[i];
x>>=1;
}
int l=read(),r=read();
for(int i=n;i<n<<1;i++) ans[i]=(ans[i]-ans[i+2]+mod)%mod;
int Ans=0;
for(int i=n+l;i<=n+r;i++) Ans=(Ans+ans[i])%mod;
printf("%d\n",Ans);
}
}
signed main(){
star::work();
return 0;
}

CF896D Nephren Runs a Cinema的更多相关文章

  1. 【CF896D】Nephren Runs a Cinema 卡特兰数+组合数+CRT

    [CF896D]Nephren Runs a Cinema 题意:一个序列中有n格数,每个数可能是0,1,-1,如果一个序列的所有前缀和都>=0且总和$\in [L,R]$,那么我们称这个序列是 ...

  2. CodeForces - 896D :Nephren Runs a Cinema(卡特兰数&组合数学---比较综合的一道题)

    Lakhesh loves to make movies, so Nephren helps her run a cinema. We may call it No. 68 Cinema. Howev ...

  3. 【题解】CF#896 D-Nephren Runs a Cinema

    容易发现这些 vip 用户并没什么用,所以考虑枚举手持50元与100元的人共有多少个.设手持50元的人 \(a\) 个,手持100元的人 \(a - k\) 个,那么一共是 \(2*a - k\) 个 ...

  4. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  5. Codeforces #380 div2 C(729C) Road to Cinema

    C. Road to Cinema time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  6. Codeforces Round #380 (Div. 2, Rated, Based on Technocup 2017 - Elimination Round 2)C. Road to Cinema 二分

    C. Road to Cinema time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  7. cf380D Sereja and Cinema 组合数学

              time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...

  8. Cinema 4D R16安装教程

    CINEMA 4D_百度百科 http://baike.baidu.com/view/49453.htm?fr=aladdin 转自百度贴吧 [教程]Cinema 4D R16新功能介绍及安装教程_c ...

  9. ZOJ 3635 Cinema in Akiba(线段树)

    Cinema in Akiba (CIA) is a small but very popular cinema in Akihabara. Every night the cinema is ful ...

随机推荐

  1. Selenium-python 之 frame定位元素

    定位元素时经常会出现定位不到元素,这时候我们需要观察标签的上下文,一般情况下这些定位不到的元素存放在了frame或者放到窗口了,只要我们切入进去就可以很容易定位到元素. 处理frame时主要使用到sw ...

  2. 【NX二次开发】开发环境搭建

    1.Visual Studio 版本按照下表选择. UG版本 VS版本 NX1847-NX1872版 Visual Studio 2017 Build 19.10.25017 NX12版 Visual ...

  3. 【题解】poj 3162 Walking Race 树形dp

    题目描述 Walking RaceTime Limit: 10000MS Memory Limit: 131072KTotal Submissions: 4941 Accepted: 1252Case ...

  4. 京东 Vue3 组件库支持小程序开发啦!

    源码抢先看: https://github.com/jdf2e/nutui NutUI 3.0 官网:https://nutui.jd.com/3x/#/ 小程序多端适配 设计初衷 在跨端小程序的开发 ...

  5. NXNSAttack漏洞简析

    漏洞简介: 该漏洞为DNS 放大攻击,是 DDoS 攻击,攻击者利用 DNS 服务器中的漏洞将小查询转换为可能破坏目标服务器的更大负载. 在 NXNSAttack 的情况下,远程攻击者可以通过向易受攻 ...

  6. win10下简单截图

    win10 下面可以 win+shift+s 拖动截图,个人感觉是最简单的

  7. Golang去除字符串前后空格

    Golang去除字符串前后空格 实现Demo package main import "fmt" func DeletePreAndSufSpace(str string) str ...

  8. 整合Spring Cloud Stream Binder与RabbitMQ进行消息发送与接收

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 前言 Spring Cloud Stream专门用于事件驱动的微服务系统,使用消息中间件来收发信息.使用Spring ...

  9. 第8章:深入理解Service

    8.1 Service存在的意义 防止Pod失联(服务发现) 定义一组Pod的访问策略(负载均衡) 8.2 为什么要使用Service Kubernetes Pod`是平凡的,由`Deployment ...

  10. 12、Linux磁盘设备基础知识(2)

    12.4.计算磁盘容量: 磁盘的大小=盘面大小*磁头数 盘面的大小=磁道大小*磁道数 磁道大小=512字节*扇区数 磁盘的大小=512字节*扇区数*磁道数*磁头数 磁盘的大小=柱面大小*柱面数 柱面大 ...