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