Test #3 2014/12/13题解
来源:互联网 发布:下载炒股模拟软件 编辑:程序博客网 时间:2024/04/30 14:21
题目地址:http://acm.njupt.edu.cn/vjudge/contest/view.action?cid=161#overview
这次的题目比较多,8个小时的时间也比较长,题目也基本都是一些算法和数据结构的基础练习题。(C那个DP有点略难)
另外提醒下在contest结束之后,Vjudge仍然允许提交,只是不再计入rank了而已,欢迎继续练习。
下面进入正题。
A - Sum of Consecutive Prime Numbers
这题是让求一个数分解成连续的若干个质数可以有多少种分解方法。
很简单,预处理一下10000以内的素数表,然后暴力枚举即可。
较为简单,附代码:
//Origin:POJ 2739//Tags: Math #include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cstdlib>using namespace std; bool Prime(int num)//判断素数 { int m; if(num==2) return true; for(m=2;m*m<=num;m++) if(num%m==0)return false; return true;}int p[2000],len,ans;int n,tot;int main(){int j=0; for(int i=2;i<10000;i++)//预处理素数表 if(Prime(i))p[++j]=i; len=j; while(true){ ans=0; scanf("%d",&n); if(n==0)return 0; for(int i=1;i<=len;i++){ tot=0; for(j=i;j<=len&&tot<n;j++) tot+=p[j]; if(tot==n)ans++; } printf("%d\n",ans); } return 0;}
B - Oulipo
这个还是KMP算法。
就是最原始的求next数组,然后进行匹配再计数可以成功匹配多少次。
附代码:
//Origin:POJ 3461//Tags:strings KMP#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;char w[10500],t[1001000];int nxt[10500],T,ans,lenw,lent;int main(){scanf("%d",&T);while (T--){scanf("%s",w);lenw=strlen(w);scanf("%s",t);lent=strlen(t);memset(nxt,0,sizeof nxt);nxt[0]=-1;int j=-1;for (int i=1;i<lenw;i++)//构造next数组 {while (j>-1 && w[j+1]!=w[i])j=nxt[j];if (w[j+1]==w[i])j++;nxt[i]=j;}ans=0;j=-1;for (int i=0;i<lent;i++)//KMP匹配 {while (j>-1 && w[j+1]!=t[i])j=nxt[j];if (w[j+1]==t[i])j++;if (j==lenw-1){ans++;j=nxt[j];}}printf("%d\n",ans);}}
C - Little Tiger vs. Deep Monkey
这个是一个稍微要动下脑子的题目。
题目大意就是答对一道题可以得a[i]分,然后求“至少得到多少分数使得至少有p的概率不会输“。
这样问题就转化成了求”得到这个分数的概率大于等于P的时候,所得分数的最小值“。
现在就只要求得到每个分数的概率即可,可以利用动态规划的思想。
因为是随机答题,机器人每次答题正确和错误的概率都是0.5
一开始没有答题,得零分的概率是1.0。然后回答了第i个问题的j分数可以由第i-1个问题时的概率状态来递推出
即
f[i][j] += f[i-1][j]*0.5; (第i-1题获得了j分时候且第i题没有答对的情况)
f[i][j+a[i]] += f[i-1][j]*0.5 (第i-1题获得了j分时候且第i题答对的情况)
然后为了节约内存,可以做一个小优化。
因为回答了第i题时候的状态只和回答了第i-1题的时候有关,所以可以只用两个数组来不停的迭代计算,具体实现见代码。
总共只有40题,最多只会有40,000分,只开两个数组的话内存占用的非常小。
理论上如果不做这个优化也不会超出空间限制,没有具体测试,但加个优化也没多多少代码。
这题是去年长春赛区区域赛现场的第二可做的题目,签到题和这题做对了,再出一题就可以稳进铜牌区了~
附代码:
//Origin:ACM/ICPC 2013 Asia Regional Changchun;HDU 4815//Tags:DP#include <cstdio>#include <cmath>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;double P;int n,a[45],ans;double f[2][40500];//即为进行迭代的dp数组 bool cur;//表示当前使用的是哪个状态 int main(){int T;scanf("%d",&T);while (T--){int tot=0;scanf("%d%lf",&n,&P);for (int i=1;i<=n;i++){scanf("%d",&a[i]);tot+=a[i];}cur=0;memset(f,0,sizeof f );f[0][0]=1;for (int i=1;i<=n;i++)//f[j]表示答了i题之后 得到分数为j的概率 {cur=!cur;//用两个数组迭代计算节省内存空间,利用取反来实现状态的迭代 memset(f[cur],0,sizeof (f[cur]));for (int j=0;j<=tot;j++){if (f[!cur][j]>0){f[cur][j]+=0.5*f[!cur][j];f[cur][j+a[i]]+=0.5*f[!cur][j];}}}for (int i=1;i<=tot;i++)f[cur][i]+=f[cur][i-1];//经过这个处理f[i]表示回答了所有题目之后,分数小于等于i的概率 for (int i=0;i<=tot;i++)if (f[cur][i]>=P){ans=i;break;}printf("%d\n",ans);}return 0;}
D - Winner
这是Codeforce #2的A题
用了一个哈希表的基本思想。(哈希表是什么东西详细见百度百科,比起之前的几个算法数据结构非常的简单易懂)
题目是要求 最后得到最高分且第一个达到这个分数的人的名字。
C++因为map的存在就非常方便了,可以直接调用map来存储数据,C得写一个哈希函数求哈希值然后颠来倒去的算各种麻烦。。
map的具体使用方法详见C++ Primer或者http://www.cplusplus.com/,非常快捷好用的一个STL。
附代码
//Origin:CodeForces 2A#include <cstdio>#include <string>#include <algorithm>#include <map>#include <iostream>using namespace std;string s[1010];int p[1010];int n,maxm;map <string,int> mp,g;//mp存储的是每个人最后达到的分数,g存储的是当前的分数 int main(){maxm=-2147483646;mp.clear();g.clear();scanf("%d",&n);for (int i=1;i<=n;i++){cin>>s[i]>>p[i];mp[s[i]]+=p[i];}for (int i=1;i<=n;i++)maxm=max(maxm,mp[s[i]]);int ans=0;g.clear();for (int i=1;!ans&&i<=n;i++)//如果ans不为0了就退出循环 if (mp[s[i]]==maxm && (g[s[i]]+=p[i])>=maxm)ans=i;cout<<s[ans]<<endl;}
E - Zhuge Liang's Password
这是2013年杭州赛区的签到题。
要求A和B两个方阵最大的匹配数是多少。
所谓匹配数即为A和B经过任意的90°旋转后,数字完全相同的位置数。
我们就可以假设A矩阵不动,B矩阵一共有4种旋转方式,分别是转0°、90°、180°、270°。
然后依次判断就行了。(n即为题目中描述的方阵的边长,以下旋转均为顺时针旋转)
转0°的时候
A[i][j]对应的B的位置就是B[i][j]
转90°时候
A[i][j]对应的B的位置是B[j][n+1-i]
转180°时候
A[i][j]对应的B的位置是B[n+1-i][n+1-j]
转270°
A[i][j]对应的B的位置是B[n+1-j][i]
然后求一下最大的匹配数量即可。
附代码:
//Origin:ACM/ICPC 2013 Asia Hangzhou Regional Contest;HDU 4772#include <cstring>#include <cstdio>#include <cstdlib>#include <map>#include <climits>#include <algorithm>using namespace std;int p[350][350],q[350][350];int tot,ans,n;int main(){while (scanf("%d",&n)&&n!=0){ans=tot=0;memset(p,0,sizeof 0);memset(q,0,sizeof 0);for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)scanf("%d",&p[i][j]);for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)scanf("%d",&q[i][j]);for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (p[i][j]==q[i][j])tot++;ans=max(ans,tot);tot=0;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (p[i][j]==q[j][n+1-i])tot++;ans=max(ans,tot);tot=0;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (p[i][j]==q[n+1-i][n+1-j])tot++;ans=max(ans,tot);tot=0;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (p[i][j]==q[n+1-j][i])tot++;ans=max(ans,tot);printf("%d\n",ans);}}
F - Ubiquitous Religions
题目描述的是有n个人(编号1-n),不方便问每个人信仰的什么宗教,但是目前已知有若干组两个人是信仰的相同的宗教,求最多有多少种宗教。
这还是一个基础的并查集题。
一开始假设每个人都信仰不同的宗教,每组两个人信仰相同的宗教即把这两个人分别所在的集合进行合并,最后求有多少个不同的集合即可。
运用一个小技巧,有多少人所在的集合编号依旧是初始编号,那么这个数量就是集合的数量。(为什么这么做是对的,可以自己思考下~)
附代码:
//Origin:POJ 2524//Tags:并查集 #include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;int n,m,x,y;int f[50100];int gt_fa(int m){return m==f[m] ? m : gt_fa(f[m]);}int main(){int nm=0; while (scanf("%d%d",&n,&m)!=EOF && (n+m) ){for (int i=1;i<=n;i++)f[i]=i;for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);f[gt_fa(x)]=gt_fa(y);}int tot=0;for (int i=1;i<=n;i++)tot+= gt_fa(i)==i ? 1 : 0;//可以通过有多少人还在自己初始所在编号的集合中,来判断有多少个不同的集合 printf("Case %d: %d\n",++nm,tot);}return 0;}
- Test #3 2014/12/13题解
- Test #1 2014/12/6题解
- Test #2 2014/12/7题解
- Intelligence test(test)题解
- codeforces A. IQ test 题解
- 2014-3-17 test
- [2016-3-13 Test]
- 【BZOJ】【P2083】【Poi2010】【Intelligence test】【题解】【二分】
- 【noip 2013 day2题解】【10.28test】
- Test.3
- 题解 BZOJ-2083 || POI 2010 intelligence test 三种解法
- 2010山东省信息学夏令营模拟赛Test 5.浇水 题解
- 2014多校3,hdu4888,hdu4893题解
- Best coder 2014-3-14题解
- 【题解】SWJTU2015.12校队选拔题解
- test Week 13
- Test 2017.10.13
- Javascript Performance Test (3)
- 算法与数据结构基础10:C++实现——拓扑排序
- 用户需求分析:背后隐藏的门槛---TOMsInsight 2014.10.12
- DWR入门教程
- LeetCode Intersection of Two Linked Lists
- onsubmit getElementById getElementByName
- Test #3 2014/12/13题解
- C – 下沙小面的(2)
- 【学习】累
- Blocks 简明实用指南(A Short Practical Guide to Blocks)
- 数据分析与R语言视频教程
- 去除工程的.svn隐藏文件夹
- 免费增值应用正在“杀死”游戏开发者?
- 头像墙效果
- IOS之触摸事件和手势