洛谷P2675 《瞿葩的数字游戏》T3-三角圣地

本文介绍了一个有趣的数学问题:如何通过排列数字1至N构建一个倒三角形,使得最终底部的数字(基)最大,并输出该值对10007取模的结果。文章提供了完整的解题思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目背景

国王1带大家到了数字王国的中心:三角圣地。

题目描述

不是说三角形是最稳定的图形嘛,数字王国的中心便是由一个倒三角构成。这个倒三角的顶端有一排数字,分别是1~N。1~N可以交换位置。之后的每一行的数字都是上一行相邻两个数字相加得到的。这样下来,最底端就是一个比较大的数字啦!数字王国称这个数字为“基”。国王1希望“基”越大越好,可是每次都自己去做加法太繁琐了,他希望你能帮他通过编程计算出这个数的最大值。但是这个值可能很大,所以请你输出它mod 10007 的结果。

任务:给定N,求三角形1~N的基的最大值 再去 mod 10007。

输入输出格式

输入格式:

一个整数N

输出格式:

一个整数,表示1~N构成的三角形的最大的“基”

输入输出样例

输入样例#1: 
4
输出样例#1: 
24
输入样例#2: 
1125
输出样例#2: 
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分。

剩下的50分:模数是个质数,组合数又很大,交给 Lucas 解决即可。。。

记得预处理阶乘。。。

附代码:

#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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值