漂亮
【问题描述】
小美今天对于数列很有兴趣。
小美打算找出一些漂亮的序列。
一个漂亮的序列的限制如下:
1. 长度为 n ,而且数列里只包含 [1,n] 的整数。
2. 要不是不降的序列就是不升的序列。
小美想知道有多少个合法的序列满足要求。
【输入格式】
从文件 pretty.in 中读入数据。
第一行一个正整数 n 表示数列的大小。
【输出格式】
输出到文件 pretty.out 中。
第一行输出一个数字表示答案。由于这个数字会很大,你需要输出他
模 1000000007。
【样例输入】
2
【样例输出】
【问题描述】
小美今天对于数列很有兴趣。
小美打算找出一些漂亮的序列。
一个漂亮的序列的限制如下:
1. 长度为 n ,而且数列里只包含 [1,n] 的整数。
2. 要不是不降的序列就是不升的序列。
小美想知道有多少个合法的序列满足要求。
【输入格式】
从文件 pretty.in 中读入数据。
第一行一个正整数 n 表示数列的大小。
【输出格式】
输出到文件 pretty.out 中。
第一行输出一个数字表示答案。由于这个数字会很大,你需要输出他
模 1000000007。
【样例输入】
2
【样例输出】
4
-------------------------------------------------------------------
50% 显然是一个dp,先求不降序,ans=不降序*2-n;
f[i][j]表示第i位,数字为j的方案数,暴力一点的话,f[i][j]=sigma(f[i+1][k]|k>=j)
这是O(n^3) ,想想如何优化,然后可以发现 f[i][j]=f[i][j-1]-f[i+1][j-1](可以画图理解),此时已是O(n^2)
然后将f数组输出一下,发现了神奇的东西
6 3 1 3 2 1 1 1 1 // n==3
这不是杨辉三角吗!
ans=sigma(C(i,n+i-1)| 0<i<n)=>(2*n-1)!/n!*(n-1)!
除法需要求逆元,直接费马小定理
#include <cstdio>//50% #include <cstring> using namespace std; const int P=1000000007; int n,ans; int f[4005][4005]; int dfs(int x,int id) { if (f[x][id]!=-1) return f[x][id]; f[x][id]=0; if (x==n) f[x][id]=1; else if (id==1) { for (int i=id;i<=n;i++) { f[x][id]=(f[x][id]+dfs(x+1,i))%P; } } else f[x][id]=(f[x][id-1]-f[x+1][id-1]+P)%P; return f[x][id]; } int main() { freopen("pretty.in","r",stdin); freopen("pretty.out","w",stdout); memset(f,-1,sizeof f); scanf("%d",&n); for (int i=1;i<=n;i++) ans=(ans+dfs(1,i))%P; ans=((ans-n)*2%P+n)%P; printf("%d",ans); }
#include <cstdio> #include <cstring> using namespace std; #define int long long const int P=1000000007; int n,ans=1; int bin[200007]={1}; int ksm(int a,int b,int p) { int s=1; for (;b;a=(a*a)%P,b>>=1) if (b&1) s=s*a%P; return s; } int C(int m,int n) { int k=bin[m]*bin[n-m]%P; return bin[n]*ksm(k,P-2,P)%P; } signed main() { freopen("pretty.in","r",stdin); freopen("pretty.out","w",stdout); scanf("%lld",&n); for (int i=1;i<=n*2;i++) bin[i]=(bin[i-1]*i)%P; for (int i=1;i<n;i++) ans=(ans+C(i,n+i-1))%P; ans=(ans*2-n+P)%P; printf("%lld",ans); }