Codeforces Round #449 Div. 1

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

posted @ 2019-03-02 01:21  Gloid  阅读(133)  评论(0编辑  收藏  举报