11月月赛

A-HDU1087   http://acm.hdu.edu.cn/showproblem.php?pid=1087

相当于从数组a中找一个最优序列,我们设要找的序列为A,序列A满足两个条件,一是A中的元素大小满足单调递增,二是A中所有元素的和最大,输出这个最大值。

令f[i]表示以第i个元素结尾的A序列的最大值,则有f[i]=MAX{ f[j]+a[i]  |  j<i }   ans=MAX{f[i]};

 1 *#include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int N,i,j,k,ans;
 6     int f[1005],a[1005];
 7     while(cin>>N&&N){
 8         memset(f,0,sizeof(f));
 9         ans=0;
10         for(i=1;i<=N;++i) cin>>a[i];
11         for(i=1;i<=N;++i){
12             int maxn=0;
13             for(j=1;j<i;++j){
14                 if(a[j]<a[i]&&f[j]>maxn) maxn=f[j];
15             }
16             f[i]=maxn+a[i];
17             ans=max(ans,f[i]);
18         }
19         cout<<ans<<endl;
20     }
21     return 0;
22 }

B-HDU5586   http://acm.hdu.edu.cn/showproblem.php?pid=5586

对于数组A可以选定任意一段连续的区间[l,r]将这段区间的值改变为: A[i]=(1890*A[i]+143)%10007; 求更改之后A数组的总和的最大值。

不妨这么想,这个最大值就是未改变之前的A数组的总和加上改变的那段区间改变以后增加的值X,问题就转化为求最大的X,

设B[i]=(1890*A[i]+143)%10007,C[i]=B[i]-A[i]; 显然X就是C数组的一个最大子段和,找到之后输出SUM{A[i]}+X即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int N,M,i,j,k,t,a,b;
 6     while(scanf("%d",&N)==1){
 7         int s=0,maxn=0,sumn=0;
 8         for(i=1;i<=N;++i){
 9             scanf("%d",&a);
10             s+=a;
11             b=1890*a+143;
12             if(b>10006) b=b%10007-a;
13             else  b-=a;
14             sumn+=b;
15             if(sumn>maxn) maxn=sumn;
16             if(sumn<0) sumn=0;
17         }
18        printf("%d\n",s+maxn);
19     }
20     return 0;
21 }

C-uva10910  https://vjudge.net/problem/UVA-10910

F(N,T,P)表示N门不同的课程,总共得分T分,没门至少得分P分,求不同的得分方案总数。

1是dp,令f(i,j)表示前i门课程得了j分的方案个数,枚举最后一门课程得分k,有f[i][j]=SUM{f[i-1][j-k] | P<=k<=T&&0<=j-k<=T}

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 int f[105][105];
 5 int main()
 6 {
 7     int T,N,P,cas,i,j,k;
 8     cin>>cas;
 9     while(cas--){
10         cin>>N>>T>>P;
11         memset(f,0,sizeof(f));
12         f[0][0]=1;
13         for(i=1;i<=N;++i)
14         {
15             for(j=P*i;j<=T;j++)
16             {
17                 for(k=P;k<=T;++k)
18                 {
19                     if(j-k<=T&&j-k>=0)
20                     f[i][j]+=f[i-1][j-k];
21                 }
22             }
23         }
24         cout<<f[N][T]<<endl;
25     }
26     return 0;
27 }

2-组合数学

利用组合数学,题目转换为将T-N*P个小球(相同)放入N个盒子(不同)的方案个数,显然是C(T-N*P+N-1,T-N*P)-------->数学公式我只会背不会推导

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 LL C(LL N,LL M)
 5 {
 6     LL ans=1;
 7     for(LL i=1;i<=M;++i)
 8     {
 9         ans=ans*(N-i+1)/i;
10     }
11     return ans;
12 }
13 int main()
14 {
15     LL N,T,P;
16     int k;
17     cin>>k;
18     while(k--){
19         cin>>N>>T>>P;
20         cout<<C(T-N*P+N-1,T-N*P)<<endl;
21     }
22     return 0;
23 }

D-HDU1243 http://acm.hdu.edu.cn/showproblem.php?pid=1243

一个标准的LCS模型,只不过多了权值,稍微改下转移方程就好了,令kill(i)表示杀死第i个人的得分

f[i][j]=MAX{f[i-1][j-1]+kill(i) | if(s1[i]==s2[j]) ,  f[i-1][j] ,  f[i][j-1] }

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int f[2105][2105];
 4 int value[30];
 5 char s1[2105],s2[2105],s[2105];
 6 int main()
 7 {
 8     int N;
 9     int i,j,k,n,m;
10     while(cin>>N){
11         cin>>s+1;
12         for(i=1;i<=N;++i) cin>>value[s[i]-‘a‘];
13         cin>>s1+1>>s2+1;
14         int len1=strlen(s1+1);
15         int len2=strlen(s2+1);
16         memset(f,0,sizeof(f));
17         for(i=1;i<=len1;++i){
18             for(j=1;j<=len2;++j){
19                 if(s1[i]==s2[j]){
20                     f[i][j]=max(f[i][j],f[i-1][j-1]+value[s1[i]-‘a‘]);
21                 }
22                 f[i][j]=max(f[i][j],max(f[i-1][j],f[i][j-1]));
23             }
24         }
25         cout<<f[len1][len2]<<endl;
26     }
27     return 0;
28 }

E-HDU2845http://acm.hdu.edu.cn/showproblem.php?pid=2845

其实就是求最大不连续子段和,先求出每一行的最大不连续子段和,再把每一行求出的值看作一个序列再求一次最大不连续子段和就是答案。

令f[i]表示前i个元素中的最大不连续子段和,有f[i]=max(f[i-1],a[i]+f[i-2]);

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int dp[200005];
 4 int h[200005];
 5 int book[200005];
 6 int n,m;
 7 int init(int a[],int len)
 8 {
 9     dp[0]=0;
10     dp[1]=a[1];
11     for(int i=2;i<=len;++i)
12         dp[i]=max(a[i]+dp[i-2],dp[i-1]);
13 return dp[len];
14 }
15 int main()
16 {
17     int i,j,k;
18     while(cin>>n>>m){int s1=0,s2=0;
19         for(i=1;i<=n;++i){
20           for(j=1;j<=m;++j)
21      scanf("%d",&h[j]);
22      book[i]=init(h,m);
23           }
24     printf("%d\n",init(book,n));
25     }
26     return 0;
27 }
时间: 2025-01-04 16:12:29

11月月赛的相关文章

csu-2018年11月月赛Round2-div2题解

csu-2018年11月月赛Round2-div2题解 A(2193):昆虫繁殖 Description 科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强.每对成虫过x个月产y对卵,每对卵要过两个月长成成虫.假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵),问过Z个月以后,共有成虫多少对?0=<X<=20,1<=Y<=20,X=<Z<=50 Input 单组数据 x,y,z的数值 Output 过Z个月以后,共有成虫对

csu-2018年11月月赛Round2-div1题解

csu-2018年11月月赛Round2-div1题解 A(2191):Wells的积木游戏 Description Wells有一堆N个积木,标号1~N,每个标号只出现一次 由于Wells是手残党,所以每次只能取出一块积木放在积木顶层 现在Wells想知道至少需要操作几次可以把积木堆成从顶至底标号升序 不论什么都很菜的Wells显然不知道怎么做 所以作为人生赢家的你义不容辞的决定帮助可怜的Wells Input 第一行一个正整数N 接下来N行,从顶至底描述每块积木的标号 Output 输出一行

洛谷11月月赛round.1

太感动了#2 thwfhk 240 (801ms) 100 100 40 又一张明信片,话说10月的怎么还没收到 P2246 SAC#1 - Hello World(升级版) 题目背景 一天,智障的pipapi正在看某辣鸡讲义学程序设计. 题目描述 在讲义的某一面,他看见了一篇文章.这篇文章由英文字母(大小写均有).数字.和空白字符(制表/空格/回车)构成. pipapi想起了他最近刚刚学会写的Hello World程序.他非常好奇,这篇文章中,“HelloWorld”作为子序列到底出现过多少次

FOJ 11月月赛题解

抽空在vjudge上做了这套题.剩下FZU 2208数论题不会. FZU 2205 这是个想法题,每次可以在上一次基础上加上边数/2的新边. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <queue

code+11月月赛

T1 SB题 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<iostream> 6 #include<algorithm> 7 #include<queue> 8 #include<set> 9 #define inf (0x7fffffff) 10 #define l(a) ((a)&

洛咕11月月赛部分题解 By cellur925

听说是你谷史上最水月赛?我不听我最菜 T1:终于结束的起点 月天歌名好评 给你一个模数 \(M\),请你求出最小的 \(n > 0\),使得\(fib(n)\) \(mod\) \(m=0\),\(fib(n+1)\) \(mod\) \(m=1\). 数学题,开始还想打表验证下,但是我不会告诉你我打表的时候没有很及时地取膜,然后中间有结果溢出,耽误了很长时间,企图找了很久规律.结果发现暴力就能过.hhh. 这个故事告诉我们要及时取膜! #include<cstdio> #include

FZU 11月月赛D题:双向搜索+二分

/* 双向搜索感觉是个不错的技巧啊 */ 题目大意: 有n的物品(n<=30),平均(两个人得到的物品差不能大于1)分给两个人,每个物品在每个人心目中的价值分别为(vi,wi) 问两人心目中的价值差最小是多少. 分析: 直接暴搜目测会超时 想到先搜索前一半,用数组a[0][i]保存第一个人在前半段取 i 个物品两个人的差的所有情况: 再搜索后一半保存两个人的差的相反数,用相同的规则保存在a[1][]中. 要想总差最小只需要 a[0][i]-a[1][num-i] (num=n/2或 n/2+1)

【BZOJ 4832 】 4832: [Lydsy2017年4月月赛]抵制克苏恩 (期望DP)

4832: [Lydsy2017年4月月赛]抵制克苏恩 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 275  Solved: 87 Description 小Q同学现在沉迷炉石传说不能自拔.他发现一张名为克苏恩的牌很不公平.如果你不玩炉石传说,不必担心,小Q 同学会告诉你所有相关的细节.炉石传说是这样的一个游戏,每个玩家拥有一个 30 点血量的英雄,并且可以用牌 召唤至多 7 个随从帮助玩家攻击对手,其中每个随从也拥有自己的血量和攻击力.小Q同学

4832: [Lydsy2017年4月月赛]抵制克苏恩]【解题报告】

戳我 4832: [Lydsy2017年4月月赛]抵制克苏恩 时间限制: 1 Sec  内存限制: 128 MB提交: 752  解决: 289[提交][][] 题目描述 小Q同学现在沉迷炉石传说不能自拔.他发现一张名为克苏恩的牌很不公平.如果你不玩炉石传说,不必担心,小Q 同学会告诉你所有相关的细节.炉石传说是这样的一个游戏,每个玩家拥有一个 30 点血量的英雄,并且可以用牌 召唤至多 7 个随从帮助玩家攻击对手,其中每个随从也拥有自己的血量和攻击力.小Q同学有很多次游戏失败都是 因为对手使用