B:注意到nc/2<=m,于是以c/2为界决定数放在左边还是右边,保证序列满足性质的前提下替换掉一个数使得其更靠近边界即可。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 1000000007
#define N 1010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,c,a[N],head,tail;
signed main()
{
n=read(),m=read(),c=read();head=1,tail=n;
while (head<=tail)
{
int x=read();
if (x<=c/2)
{
bool flag=0;
for (int i=1;i<head;i++) if (a[i]>x) {cout<<i<<endl;a[i]=x;flag=1;break;}
if (!flag) cout<<head<<endl,a[head++]=x;
}
else
{
bool flag=0;
for (int i=n;i>tail;i--) if (a[i]<x) {cout<<i<<endl;a[i]=x;flag=1;break;}
if (!flag) cout<<tail<<endl,a[tail--]=x;
}
}
for (int i=1;i<=n;i++) cout<<a[i]<<' ';cout<<endl;
return 0;
//NOTICE LONG LONG!!!!!
}
D:相当于求有多少个-1 0 1构成的序列满足前缀和始终不小于0且总和在[l,r]中。这个前缀和限制非常容易想到卡特兰数,考虑类似的推式子方法,写出dp式子然后造一个网格图,如果没有前缀和限制只要暴力枚举1的个数算一下组合数即可,而所有不满足前缀和限制的方案与从边界走过来的方案一一对应,于是减掉就可以了(具体见NOI2018冒泡排序?)。于是只剩下模数不是质数的问题,对其分解质因数,然后阶乘及其逆元拆成两部分,与模数互质部分直接处理,剩下的记录每个质因子幂次做前缀和即可求组合数。最坑的一点大概是因为模数可达2e9无法避免爆int。为什么这个小水题过的人这么少
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define int long long
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,P,l,r,fac[N],inv[N],sum[N][30],p[30],t;
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
void exgcd(int &x,int &y,int a,int b)
{
if (b==0)
{
x=1,y=0;
return;
}
exgcd(x,y,b,a%b);
int t=x;x=y;y=t-a/b*x;
}
int Inv(int a)
{
int x,y;
exgcd(x,y,a,P);
return (x%P+P)%P;
}
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int C(int n,int m)
{
if (m>n) return 0;
int ans=1ll*fac[n]*inv[m]%P*inv[n-m]%P;
for (int i=1;i<=t;i++) ans=1ll*ans*ksm(p[i],sum[n][i]-sum[m][i]-sum[n-m][i])%P;
return ans;
}
int calc(int m)
{
int ans=0;
for (int i=0;i<=n;i++)
inc(ans,1ll*C(n,i)*C(n-i,m+i)%P);
return ans;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
#endif
n=read(),P=read(),l=read(),r=read();
int u=P;
for (int i=2;i*i<=u;i++)
if (u%i==0) {p[++t]=i;while (u%i==0) u/=i;}
if (u>1) p[++t]=u;fac[0]=1;
for (int i=1;i<=n;i++)
{
int x=i;
for (int j=1;j<=t;j++)
{
sum[i][j]=sum[i-1][j];
while (x%p[j]==0) x/=p[j],sum[i][j]++;
}
fac[i]=1ll*fac[i-1]*x%P;
}
for (int i=0;i<=n;i++) inv[i]=Inv(fac[i]);
cout<<((calc(l)+calc(l+1)-calc(r+2)-calc(r+1))%P+P)%P;
return 0;
//NOTICE LONG LONG!!!!!
}
布星lxl题一点都不会。