题目背景
国王1带大家到了数字王国的中心:三角圣地。
题目描述
不是说三角形是最稳定的图形嘛,数字王国的中心便是由一个倒三角构成。这个倒三角的顶端有一排数字,分别是1~N。1~N可以交换位置。之后的每一行的数字都是上一行相邻两个数字相加得到的。这样下来,最底端就是一个比较大的数字啦!数字王国称这个数字为“基”。国王1希望“基”越大越好,可是每次都自己去做加法太繁琐了,他希望你能帮他通过编程计算出这个数的最大值。但是这个值可能很大,所以请你输出它mod 10007 的结果。
任务:给定N,求三角形1~N的基的最大值 再去 mod 10007。
输入输出格式
输入格式:一个整数N
一个整数,表示1~N构成的三角形的最大的“基”
输入输出样例
4
24
1125
700
说明
数据:
20% 0<=N<=100
50% 0<=N<=3000
100% 0<=N<=1000000
样例解释:
1 3 4 2
4 7 6
11 13
24
是N=4的时候的最大值,当然还有别的构成形式。
题解:
观察发现越大的数排在中间位置对答案越有利,所以就可以贪心了。。。
而不同位置对答案有不同的贡献次数
拿样例举例
1 3 4 2
那么第一个位置1对答案贡献1次
第二个位置3对答案贡献3次
第三个位置4对答案贡献3次
第四个位置2对答案贡献1次
即:
a b c d
(a+b) (b+c) (c+d)
(a+2*b+c) (b+2*c+d)
(a+3*b+3*c+d)
不难发现这个贡献次数为杨辉三角(就是组合数)
我们可以O(n^2)求出组合数对10007的取模
ans = sigma ( C ( n , i ) * i ) ( i = 1 ~ n )
于是就有了50分。附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MOD 10007
#define MAXN 1000010
using namespace std;
long long f[MAXN],inv[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
long long mexp(long long a,long long b,long long c){
long long s=1;
while(b){
if(b&1)s=s*a%c;
a=a*a%c;
b>>=1;
}
return s;
}
long long lucas(long long n,long long m,long long p){
if(n<m)return 0;
if(m>=p||n>=p)return lucas(n/p,m/p,p)%p*lucas(n%p,m%p,p)%p;
if(m>n-m)m=n-m;
return f[n]*inv[m]%MOD*inv[n-m]%MOD;
}
void make(){
int m=MOD-1;
f[0]=f[1]=inv[0]=inv[1]=1;
for(int i=2;i<=m;i++){
f[i]=f[i-1]*i%MOD;
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
}
for(int i=1;i<=m;i++)inv[i]=inv[i-1]*inv[i]%MOD;
}
int main(){
long long ans=0;
int n=read();
make();
for(int i=1;i<=n;i++){
if(i%2)ans=(ans+lucas(n-1,(i+1)/2-1,MOD)*i+MOD)%MOD;
else ans=(ans+lucas(n-1,n-i/2,MOD)*i+MOD)%MOD;
}
printf("%lld\n",ans%MOD);
return 0;
}