AT_abc178_d 题解

洛谷链接&Atcoder 链接

本篇题解为此题较简单做法较少码量,并且码风优良,请放心阅读。

1|0题目简述

给定一个正整数 S,问有多少个数满足以下条件:

  • 序列中必须为 3 的正整数。
  • 序列中的和必须为 S

2|0思路

首先想到组合数学,本题可通过组合数学插板法解决。

引入:例题,求 n 个苹果分为 k 组的方案数每组苹果个数仅需 1

那么这道题就可转化为:

SonoSlack

如图,共有 n 个苹果用 k1隔板隔开 k 组,即n1 个空中选 k1 个空插隔板,所以答案即为 Cn1k1

注意:隔板不能重合也不能在两边,因为每组苹果个数需 1

现在再来看此题,发现每组需 3组数不确定,所以需要枚举组数 i1n/3,并且空格数即可插板的位置数也会发生变化

n1n2×i1

隔板数依然不变,是 i1。所以对于此题,方案数即为 Cn2×i1i1

接下来就需要解决组合数的计算了,因为此题的数据范围不大,所以就可以用杨辉三角预处理组合数。学过组合数的同学应该都学过,这里直接说结论:杨辉三角的第 n 行的第 i 个数即为 Cni 的值

预处理如下(预处理过程中也要模 1000000007):

for(int i = 0; i <= n; i ++) { C[i][0] = C[i][j] = 1; for(int j = 1; j < i; j ++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; }

经过以上分析及部分代码讲解,基本的代码框架就很清晰了,下面是具体代码实现

#include<iostream> using namespace std; #define MOD 1000000007 int S, C[2005][2005]; // 组合数数组 long long ans = 0; // 记录答案,可不开 long long int main() { cin >> S; for(int i = 0; i <= S; i ++) { C[i][0] = C[i][j] = 1; for(int j = 1; j < i; j ++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; // 杨辉三角预处理组合数 } // 枚举组数 for(int i = 1; i <= S / 3; i ++) ans = (ans + C[S - 2 * i - 1][i - 1]) % MOD; // 累计答案 cout << ans << endl; // 输出答案,换行好习惯 return 0; }

提交记录:

提交记录

The End!


__EOF__

本文作者So_noSlack
本文链接https://www.cnblogs.com/So-noSlack/p/17583208.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   So_noSlack  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示