新生排位赛第三场 快速幂 hash散列
来源:互联网 发布:摇粒绒 优衣库 知乎 编辑:程序博客网 时间:2024/06/16 22:05
第四题运用了快速幂的知识
第五题运用了hash散列的知识
第一题
虽然是一道签到题,但是注意格式输出问题,后面不要多加空格
不过我到现在还没弄明白七段管是怎么回事
学长有更简洁的方法
我的太多case代码太长
429. 学姐的数码管
题目描述
学姐的七段数码管玩的出神入化。 现在给你一个浮点数,你需要把它以七段数码管的形式输出出来。 一个
输入格式
输入有多组数据,数据不超过100组,每组数据给一个整数
输出格式
输出他的数码管显示。每组数据末尾输出一个空行。
输入样例
3 23303 14564 78.9
输出样例
### ### ### ### # # # # # # # # # #### ### ### # ## # # # ## # # # #### ### ### ### # # # ### ### # # # # # # # # # # # ### ### ### # # # # # # # # # # # # ### ####### #### #### # # # # # # # # # # # # # # # # #### #### # # # # # # # # # # # # # #### # ####
#include <iostream>#include <cstdio>#include <string.h>#include <vector>#include <cmath>#include <algorithm>#include <queue>using namespace std;char a[25][50];//数组大小也要开得合适int main(){ int n, m; int first, last; char b[5]; while(~scanf("%d %s", &n, b)) { //itoa(m, b, 10);这个地方多余担心了,char非常好用,根本不需要用到itoa memset(a, ' ', sizeof a);//初始化所有都为空格,memset是一个字节一个字节初始化的,它在string.h头文件里,针对的就是字符的初始化 last = -1; for (int i=0; i<4; i++) { if (b[i] == '.')//如果是小数点单独列出 { a[2*n][last+1] = '#';//先给区域内都预先打上‘#’ last += 2; continue; } for (int k=0; k<(2*n+1); k++) for (int j=last+1; j<last+n+1; j++) a[k][j] = '#'; switch(b[i]) { case '0': //接下来是对每种情况的单独考虑,在指定区域将‘#’替换成空格 //每种情况大同小异,考虑到数组的储存方式,外面大循环是k(高) 里面小循环是j(宽)可能会更好 for (int k=1; k<(2*n); k++) for (int j=last+2; j<last+n; j++) a[k][j] = ' '; break; case '1': for (int k=0; k<(2*n+1); k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; break; case '2': for (int k=1; k<n; k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; for (int k=n+1; k<(2*n); k++) for (int j=last+2; j<last+n+1; j++) a[k][j] = ' '; break; case '3': for (int k=1; k<n; k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; for (int k=n+1; k<(2*n); k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; break; case '4': for (int k=0; k<n; k++) for (int j=last+2; j<last+n; j++) a[k][j] = ' '; for (int k=n+1; k<=(2*n); k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; break; case '5': for (int k=1; k<n; k++) for (int j=last+2; j<last+n+1; j++) a[k][j] = ' '; for (int k=n+1; k<(2*n); k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; break; case '6': for (int k=1; k<n; k++) for (int j=last+2; j<last+n+1; j++) a[k][j] = ' '; for (int k=n+1; k<(2*n); k++) for (int j=last+2; j<last+n; j++) a[k][j] = ' '; break; case '7': for (int k=1; k<(2*n+1); k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; break; case '8': for (int k=1; k<n; k++) for (int j=last+2; j<last+n; j++) a[k][j] = ' '; for (int k=n+1; k<(2*n); k++) for (int j=last+2; j<last+n; j++) a[k][j] = ' '; break; case '9': for (int k=1; k<n; k++) for (int j=last+2; j<last+n; j++) a[k][j] = ' '; for (int k=n+1; k<(2*n); k++) for (int j=last+1; j<last+n; j++) a[k][j] = ' '; break; } last += n+1; } for (int k=0; k<(2*n+1); k++) { for (int j=0; j<last; j++)//因为有last的引用,所以不会有多打空格的情况出现 cout << a[k][j]; cout << endl;//注意细节吧,换行要特别小心 } cout << endl; } return 0;}
第二题 本题可能有点坑的是方向问题,我画了半天转了好几个圈,才弄明白顺时针转指定角度就行,注意给的数对90取商后,还要对4取余
430. 学姐的旋转图像
题目描述
学姐在学图形学,然后写了一个能让图片逆时针转圈的程序。这个程序很厉害,只要输入灰度图片和旋转过的角度(90的倍数),就可以输出一个新图片。给你一张图片的灰度矩阵,和它已转过的角度,请输出图片旋转前的灰度图矩阵。
输入格式
接下来给出图片扫描稿的高H和宽W,图片的灰度矩阵,高宽都小于500,题目其他的所有数值都小于int的范围。多组数据,组数小于20,EOF结束。
输出格式
一个矩阵
输入样例
2 2 1800 11 2
输出样例
2 11 0
<span style="font-size:14px;">/*USER_ID: test#zspPROBLEM: 430SUBMISSION_TIME: 2014-07-18 14:40:11*/#include <iostream>#include <cstdio>#include <string.h>#include <vector>#include <cmath>#include <algorithm>#include <queue>using namespace std;int a[505][505];int b[505][505];int main(){ int h, w, rod; while (~scanf("%d %d %d", &h, &w, &rod)) { memset(a, 0, sizeof a); for (int i=0; i<h; i++) for (int j=0; j<w; j++) scanf("%d", &a[i][j]); if ((rod/90)%4 == 1)//注意仔细读题,是90的整数倍还要取4的余数 { for (int i=0; i<w; i++) { for (int j=0; j<h; j++) b[i][j] = a[h-1-j][i]; } swap(h, w);//长和宽也要注意,swap函数还是很好用的 } else if ((rod/90)%4 == 3)// { for (int i=0; i<w; i++) for (int j=0; j<h; j++) b[i][j] = a[j][w-1-i]; swap(h, w); } else if ((rod/90)%4 == 2)// { for (int i=0; i<h; i++) for (int j=0; j<w; j++) b[i][j] = a[h-1-i][w-1-j]; } else { for (int i=0; i<h; i++) for (int j=0; j<w; j++) b[i][j] = a[i][j]; } for (int i=0; i<h; i++)//同样要注意不要多打空格 { for (int j=0; j<w-1; j++) printf("%d ", b[i][j]); printf("%d\n", b[i][w-1]);//这样保证最后一个空格不会多打 } } return 0; }</span>
第三题 hash散列
关于hash 散列,我们要选好三个数字,
第一个是散列值,本题选取了 long long 的最大值,差不多是,10的18次方以上,因为两个long long 爆掉以后会自动取模,所以直接就不用写了,相当于我们把每个字符散列在long long的最大值这么大的范围上
而另外一个是将字符串转变成数字时用的b,这个数字的选取大了不好小了也不好,我做了好几组数据(包括10000007,19,29)的检测,最后发现对于本题的数据271是时间最短的.
后来又仔细一看,发现我错了,其实没多少差别,这种东西如果结果相差不大,就没必要纠结了,一摸一样的代码多交几遍时间也会不同
第三个数字是构建vector数组的大小,将模后的值储存在一个不大不小空间的vector向量数组里,太大了白白占用空间,太小了每条链拉得太长也不好,本题选取的是100007;没有做后续数据检测别的是否更好
还有一个相当惊人的发现,在上一场的总结报告中曾经提过string和string.h的头文件是不一样的,事实上string是c++独有的string类的头文件,而string.h其实相当于cstring
,(其包括memset函数)其实是c的函数的头文件,在本题中如果多加一个string(c++)头文件竟然会慢几十毫秒.(其实可能相差不大,可能和主机本身也有关系,我多虑了)
408. 字符串
题目描述
维护一个字符串集合:初始为空,依次处理一些插入操作,并在插入之后输出该字符串在集合中出现的次数。
字符串的长度不超过100,字符串个数不超过100000。
输入格式
输入文件包含若干行,每行为一个字符串,依次代表一个待插入的字
符串。该字符串一定非空,且仅包含英文字母和数字。
输出格式
对于每个插入操作输出一行一个整数,代表插入该字符串之后,该字
符串在集合中出现的次数。
输入样例
str1str2str1str1str2str3
输出样例
112321
#include <iostream>#include <cstdio>#include <string.h>//#include <string>//这个加上后竟然会时间增加几十秒#include <vector>#include <cmath>#include <algorithm>#include <queue>#include <fstream>#define maxn 100007using namespace std;typedef unsigned long long ull;vector <ull> a[100008];int main(){ int t; char sl[105]; //string ull temp = 0; for (int i=0; i<100008; i++) a[i].clear(); while(~scanf("%s", sl)) { temp = 0; //int len = sizeof sl; int len = strlen(sl); for (int i=0; i<len; i++) temp = (temp*271 + sl[i] - '0'); int temp2 = temp%maxn; int ans = 1; for (int i=0; i<a[temp2].size(); i++) { if (a[temp2][i] == temp) ans++; } a[temp2].push_back(temp); printf("%d\n", ans); } return 0;}
第四题 快速幂
题目规律非常好找,4的(n-1)次方,但是我一开始想开个10的九次方大的数组预先储存每个n对应的ans,不过显然时间大大超乎我的预料,估计得一分多钟才能跑一遍,后来我去掉几个零还要几秒。不过显然是因为我不知道快速幂这个东西。于是我想这么大,难不成是对1000000007的模,循环有规律,于是用文件输出,学习上次学长教的用写字板找规律,竟然随便选了几个数用查找功能还告诉我没重复的,所以白忙活了半天
这里再推荐一下怎么用文件输出结果
#include <fstream>//加一个头文件,当然还要别的头文件using namespace std;int main(){ ofstream outfile("b.txt");//这里要注意如果分开写要改成下面加个“.open” /*ofstream outfile; outfile.open("b.txt");*/ for (int i=0; i<100; i++) outfile << i << " "; outfile.close(); return 0;}
D. 田田的账号 2014新生暑假个人排位赛03
题目描述
田田申请了一个新的oj账号,打算取一个霸气而简单的名字。 什么叫简单呢?说白了田田脑子不好使,只能记住abcd这4个字母组成单词。 怎么叫霸气呢?田田认为a个个数一定要有奇数个,b的个数一定要有偶数个(包括0)才可以。 现在田田取了一个长为n的账号,但是由于田田的记性实在太差了,而把账号忘记了. 于是把这个问题交给了聪明的wzt,而他认为这道题太过于简单就把这道题交给了你 究竟这个账号有多少种可能?你只需得到这个结果模
输入格式
多组case,第一行为case数
输出格式
一个case对应一行输出
输入样例
212
输出样例
14
<span style="font-size:18px;">/*USER_ID: test#zspPROBLEM: 428SUBMISSION_TIME: 2014-07-18 16:46:42*/#include <iostream>#include <cstdio>#include <string.h>#include <vector>#include <cmath>#include <algorithm>#include <queue>#include <fstream>#define maxn 1000000007using namespace std;int a[100005];long long cal(int n){ if (n<=100000) return a[n]; else return cal(n/2)*cal(n/2)%maxn*a[n-(n/2)*2]%maxn;}int main(){ a[0] = 1; a[1] = 4; for (int i=2; i<=100000; i++) { a[i] = (long long)a[i-1]*4%maxn; } int T; scanf("%d", &T); while (T--) { int m; scanf("%d", &m); int ans = cal(m-1); printf("%d\n", ans); } return 0; }</span>
再来研究一下快速幂
快速幂模板
//下面是 m^n % k 的快速幂:// m^n % kint quickpow(int m,int n,int k){ int b = 1; while (n > 0) { if (n & 1)//按位与运算,可以判断n的奇偶性,也可以判断n的二进制最后一位是1还是0(当然这两个本质是一样的) b = (b*m)%k; //显然如果n的二进制末尾是1就要归入计算,末尾不是0就不计算 n = n >> 1 ; m = (m*m)%k; } return b;}
当然不能照抄啦,我们题目的这个数据比较大要强制类型转换一下,不然会爆,而且Int爆了估计就变0了,long long 爆了会自动取long long 最大级别的模
#include <iostream>#include <cstdio>#include <string.h>#include <vector>#include <cmath>#include <algorithm>#include <queue>#include <fstream>#define maxn 1000000007using namespace std;int quickpow(int m,int n,int k){ int b = 1; while (n > 0) { if (n & 1)//按位与运算,可以判断n的奇偶性,也可以判断n的二进制最后一位是1还是0(当然这两个本质是一样的) b = ((long long)b*m)%k; //显然如果n的二进制末尾是1就要归入计算,末尾不是0就不计算 n = n >> 1 ; m = ((long long)m*m)%k; } return b;}int main(){ int T; scanf("%d", &T); while (T--) { int m; scanf("%d", &m); //int ans = cal(m-1); printf("%d\n", quickpow(4, m-1, maxn)); } return 0;}
实验数据证明快速幂的时间比我自己那个快多了,初步验证了一下,快速幂9秒(针对此题)我的预处理了一个a[100005]的数组要32毫秒,如果没有预处理,自己试运行了一下求一个10的9次方就好几秒,模板果然好啊
快速幂模板链接(包括还有矩阵的)
第五题
- 新生排位赛第三场 快速幂 hash散列
- 新生排位赛第五场 矩阵快速幂
- ACM新生选拔赛第三场题解
- 新生排位赛第四场 dp
- 新生训练个人排位赛第二场
- 散列hash小结
- 散列(hash)
- 散列hash
- Hash散列存储
- 散列(hash)
- Hash(哈希/散列)
- 散列(hash table)
- 散列(Hash)
- 散列(hash)
- 20130712 【南华大学 ACM】 新生赛第三场 【B. A simple problem】
- 20130712 【南华大学 ACM】 新生赛第三场 【F. Help Johnny】
- 新生排位赛第一场 dp 大数处理与模板
- 单向散列函数(Hash)
- 面试算法(四十六)求1+2+.....+n
- C++ Binary Tree(二叉树)
- matlab 字符串处理函数
- j2ee成长路线
- 你需要了解的SQL知识
- 新生排位赛第三场 快速幂 hash散列
- Google打不开了就进来看看
- C# 委托实例(跨窗体操作控件)
- 新的旅程
- 最长公共子列和最长公共子串。LCS && LCSL
- Iphone开发之UIView中的动画属性
- mysql使用经验
- 2014年Q1Q2教育类投融资小结
- 程序员专业英语词汇