首页 > 其他分享 >[NOIP2012 普及组] 摆花

[NOIP2012 普及组] 摆花

时间:2023-09-21 18:57:55浏览次数:48  
标签:std 摆花 普及 return NOIP2012 int cnt maxn

[NOIP2012 普及组] 摆花

[NOIP2012 普及组] 摆花

题意

有 \(n\) 个数,每种可以选 \(0 \le x_i \le a_i\) 个,问有多少种方法可以使得 \(\sum_{i=1}^n x_i = m\) 。

Solution

1. 深搜 \(dfs\)

显然可以先暴力深搜。

#include "bits/stdc++.h"
using namespace std;
const int maxn = 110,mod = (int)1e6 + 7;
int a[maxn],n,m;
int dfs(int k,int cnt)
{
	if (cnt > m) return 0;
	if (cnt == m) return 1;
	if (k > n) return 0;
	int ret = 0;
	for (int i = 0;i <= a[k];i++)
		ret = (ret + dfs(k+1,cnt+i)) % mod;
	return ret;
}

int main()
{
	cin.tie(0); cout.tie(0);
	ios::sync_with_stdio(0);
	
	cin >> n >> m;
	for (int i = 1;i <= n;i++)
		cin >> a[i];
	cout << dfs(1,0);
	return 0;
}

显然会得到一个大大的 \(\Huge TLE\),但是有30pts呀

2. 深搜优化

众所周知,深搜可以用记忆化搜索来优化, \(f_{i,j}\) 可以表示选到第 \(i\) 个数,已经选了 \(j\) 个数有多少种方案。

#include "bits/stdc++.h"

using namespace std;

const int maxn = 110,mod = (int)1e6 + 7;

int a[maxn],n,m,f[maxn][maxn];


int dfs(int k,int cnt)
{
	if (cnt > m) return 0;
	if (cnt == m) return 1;
	if (k > n) return 0;
	if (f[k][cnt]) return f[k][cnt];
	int ret = 0;
	for (int i = 0;i <= a[k];i++)
		ret = (ret + dfs(k+1,cnt+i)) % mod;
	return f[k][cnt] = ret;
}

int main()
{
	cin.tie(0); cout.tie(0);
	ios::sync_with_stdio(0);
	
	cin >> n >> m;
	for (int i = 1;i <= n;i++)
		cin >> a[i];
	cout << dfs(1,0);
	return 0;
}

一个浅浅的记忆化搜索,就可以过这道题了,毕竟 \(n,m \le 100\) 。

3.DP

一般来说,可以用记忆化搜索AC的题,也可以用DP做。
\(dp_{i,j}\) 表示用了前 \(i\) 个数,共选了 \(j\) 个数的方案数。
那么状态转移方程就是 $f_{i,j} = \sum_{k = 0}^{min(a_i,\space j)} f_{i-1,j - k} $ 。

#include "bits/stdc++.h"

using namespace std;

const int maxn = 110,mod = (int)1e6 + 7;

int a[maxn],dp[maxn][maxn];

int main()
{
	cin.tie(0);cout.tie(0);
	ios::sync_with_stdio(0);
	
	int n,m;
	cin >> n >> m;
	
	for (int i = 1;i <= n;i++)
		cin >> a[i];
	
	dp[0][0] = 1;
	
	for (int i = 1;i <= n;i++)
		for (int j = 0;j <= m;j++)
			for (int k = 0;k <= min(j,a[i]);k++)
				dp[i][j] = ( dp[i][j] + dp[i-1][j-k] ) % mod;
	cout << dp[n][m];
	
	return 0;
}

时间复杂度 \(O(nma_i)\) ,显然能过。

标签:std,摆花,普及,return,NOIP2012,int,cnt,maxn
From: https://www.cnblogs.com/Laughing-114514/p/luogu-P1077.html

相关文章

  • P1056 NOIP2008 普及组 排座椅
    \(P1056\)[\(NOIP2008\)普及组]排座椅题解先想一下算法:因为题目里出现了最优解,最好的方案关键字,所以一定会用贪心。然后从题目给的样例解释可以看到:如果相邻的两行有许多组说话的同学,那么在这两行中间加一条过道是非常划算的;同理,列也是如此。恍然大悟,只要找出划分哪些......
  • P1082 [NOIP2012 提高组] 同余方程
    转载自这里问题转化题目问的是满足\(ax\bmodb=1\)的最小正整数\(x\)。(a,b是正整数)但是不能暴力枚举\(x\),会超时。把问题转化一下。观察\(ax\bmodb=1\),它的实质是\(ax+by=1\):这里\(y\)是我们新引入的某个整数,并且似乎是个负数才对。这样表示是为了用扩展欧几里......
  • P2669 [NOIP2015 普及组] 金币
    题目背景NOIP2015普及组T1题目描述国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连......
  • P1009 [NOIP1998 普及组] 阶乘之和
    题目描述用高精度计算出 S=1!+2!+3!+\cdots+n!S=1!+2!+3!+⋯+n!(n\le50n≤50)。其中 ! 表示阶乘,定义为 n!=n\times(n-1)\times(n-2)\times\cdots\times1n!=n×(n−1)×(n−2)×⋯×1。例如,5!=5\times4\times3\times2\times1=1205!=5×4×3×2×1=......
  • 普及一点基础语法知识
    https://www.bilibili.com/read/cv25225883/ 作者:Larry想做技术大佬https://www.bilibili.com/read/cv25225883/出处:bilibili 公布下答案,以及,顺便普及一点基础语法知识。 eoplelieallthetime,it'sauniversalthing.这个句子的所谓“语法错误”,没那么容易分析,我......
  • P1042 [NOIP2003 普及组] 乒乓球
    [NOIP2003普及组]乒乓球题目背景国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分......
  • 82 贪心 [NOIP2012 提高组] 国王游戏
    视频链接: LuoguP1080[NOIP2012提高组]国王游戏#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>usingnamespacestd;structnode{inta,b;booloperator<(node&t){returna*b<t.a*t.b;}}......
  • NOIP2012提高组初赛易错题解析
    一.3. 错误原因:忘记了解析:Intel是全球最大的CPU厂商,AMD是世界上首个研发出7纳米CPU的厂商 6.错误原因:忘记了解析:ENIAC是世界上首台计算机,属于第一代计算机,即电子管计算机 10.错误原因:选项理解错误解析:A由蝙蝠,发明雷达是正确的,B因特网的发明与蜘蛛网无关,只是形......
  • 【LGR-156-Div.3】洛谷网校 8 月普及组月赛 I & MXOI Round 1 & 飞熊杯 #2(同步赛)
    【LGR-156-Div.3】洛谷网校8月普及组月赛I&MXOIRound1&飞熊杯#2(同步赛)\(T1\)luoguP9581宝箱\(100pts\)水题,模拟即可。intmain(){ inta,b,ans=0; cin>>a>>b; if((a<0&&b<0)||(a>0&&b>0)) { cout<<max(abs(a),abs......
  • 2019年牛客普及模拟赛5
    字符统计:给出一个只包含空格和小写字母的字符串,问出现次数最多的字符(多个字符按照字典序输出)签到题。#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intsum[250];charans[250];signedmain(){ //freopen("T1.in","r",stdin); //freopen("T1.out"......