欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Codeforces Round #449 Div. 1

程序员文章站 2022-03-11 12:04:23
...

  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题一点都不会。