2017中国大学生程序设计竞赛
来源:互联网 发布:黑马程序员训练营 编辑:程序博客网 时间:2024/06/07 16:21
首先.这次开局烂到家了,1200+人过了的03签到题,我队还一直在MLE中,因为怕超时,复杂度算不清不敢暴力.
最后还是过了07 05 04 之后才稳一点慢慢的改一点交一点 ...罚时爆炸的过了03..
hdu 6152 && 1003 Friend-Graph
这个题真的暴力也能过?还飞快.暴力不是 n3 吗. 哦不,好像并不是n3的.
这个题内存卡的比较紧,直接一个bool 类型了.
当时这个签到题我们队是最后出的,卡了很久,我一开始想并查集最后被推翻了,然后队友想了 最大团来做.然后就一直MLE.我最后写了个暴力,寻思直接是n3 我用两个vector 来存有边的和无边的,两种情况分别找,然后还想这记录1的个数多,还是0的个数多.来优化常数,可惜 都没用!!!因为MLE。。。
当时可能看到1200+人过有点不淡定了...没想到这么优雅的暴力呢.
PS: 主要是这个题目有个定理,保证6个点以上一定bad,所以很快就退出.
#include<iostream>#include<cstdio>#include<string.h>using namespace std;const int maxn = 3e3;bool w[maxn][maxn];bool flag(int n){ for(int i = 1; i <= n; ++ i) { for(int j = i + 1; j <= n; ++ j) { for(int k = j + 1; k <= n; ++ k) { if(w[i][j] == w[i][k] && w[i][k] == w[j][k] && w[i][j] == w[j][k]) return true; } } } return false;}int main(){ int t, n, m; scanf("%d", &t); while(t --) { scanf("%d", &n); for(int i = 1; i < n; ++ i) { for(int j = 1 + i; j <= n; ++ j) { scanf("%d", &m); if(m == 1) w[j][i] = w[i][j] = false; else w[j][i] = w[i][j] = true; } } if(flag(n)) printf("Bad Team!\n"); else printf("Great Team!\n"); } return 0;}
队友的xjb做法:
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;#include<cstdio>#include<cstring>#define N 3005bool flag[N], a[N][N];int ans, cnt[N], group[N], n, vis[N];bool dfs( int u, int pos ){ if(ans >= 3) return 1;//因为递归层数太多,所以这里加了个剪枝.... int i, j; for( i = u+1; i <= n; i++){ if( cnt[i]+pos <= ans ) return 0; if( a[u][i] ) { for( j = 0; j < pos; j++ ) if( !a[i][ vis[j] ] ) break; if( j == pos ) { vis[pos] = i; if( dfs( i, pos+1 ) ) return 1; } } } if( pos > ans ) { for( i = 0; i < pos; i++ ) group[i] = vis[i]; ans = pos; return 1; } return 0;}void maxclique(){ ans=-1; for(int i=n;i>0;i--) { vis[0]=i; dfs(i,1); cnt[i]=ans; }}int main(){ int t; scanf("%d", &t); while(t--) { memset(a, 0, sizeof(a)); scanf("%d", &n); for(int i = 1; i <= n-1; i++) { for(int j = 1; j <= n-i; j++) { scanf("%d", &a[i][i+j]); a[i+j][i] = a[i][i+j]; } } int ans1, ans2; maxclique(); ans1 = ans; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) a[i][j] = !a[i][j]; maxclique(); ans2 = ans; if(ans1 >= 3 || ans2 >= 3) puts("Bad Team!"); else puts("Great Team!"); } return 0;}
hdu 6153 &&1004 A Secret
队友过得,我还没学会,正解好像是扩展KMP?也可能是他瞎搞的
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 2e6+10;const int mod = 1e9+7;char str[maxn], str1[maxn], str2[maxn];int len, len3;int nt[maxn], nt3[maxn];ll res[maxn], res3[maxn];void getNext1(){ nt[0] = -1; int i = 0, j = -1; while (i <= len) { if (j == -1 || str[i] == str[j]) nt[++i] = ++j; else j = nt[j]; }}void getNext2(){ nt3[0] = -1; int i = 0, j = -1; while (i <= len3) { if (j == -1 || str2[i] == str2[j]) nt3[++i] = ++j; else j = nt3[j]; }}int main(){ int t; cin >> t; while(t--) { memset(res, 0, sizeof(res)); memset(res3, 0, sizeof(res3)); memset(nt, 0, sizeof(nt)); memset(nt3, 0, sizeof(nt3)); scanf(" %s %s", str1, str2); int len1 = strlen(str1); int len2 = strlen(str2); for(int i = 0; i < len1/2; i++) swap(str1[i], str1[len1-i-1]); for(int i = 0; i < len2; i++) str[len2-i-1] = str2[i]; str[len2] = '#'; for(int i = len2+1; i < len1+len2+1; i++) str[i] = str1[i-len2-1]; str[len1+len2+1] = 0; len = len1+len2+1; len3 = len2;// cout << str << endl; getNext1(); for(int i = 0; i < len2/2; i++) swap(str2[i], str2[len2-i-1]); getNext2();// cout << str << endl; ll ans = 0;// int len = len1+len2+1; for(int i = len; i >= 1; i--) { res[i]++; res[nt[i]] += res[i]; } for(int i = len3; i >= 1; i--) { res3[i]++; res3[nt3[i]] += res3[i]; }// cout << str << ' ' << str2 << endl;// for(int i = 1; i <= len2; i++)// cout << res[i] << ' ' << res3[i] << endl; for(ll i = 1; i <= len2; i++) {// cout << i << ' ' << res[i] << endl; ans = (ans+(res[i]-res3[i])*i)%mod; } printf("%lld\n", ans); } return 0;}
hdu 6154 &&1005 CaoHaha's staff
正解找规律. 但是我队找规律比较菜啊....
我是用了二分做的...
当然这个题目数据在大点 可能就要二分了吧。。
首先我看到题目的时候...好久队友给我讲明白了题意,我看求最小,立马套二分啊,诶 ?满足单调性.即走k步可以凑出的面积 k+1 步一定也可以啊.
好,那么就像怎么check,这个check其实感觉就好找到的规律差不多了,首先我要想使面积最大,我肯定优先走对角线,因为横着和斜着斜着每次增加 根2的长度.那么对于相同的步数的话,我肯定要是长宽越接近凑出的面积尽可能的大. 那么我先考虑步数为偶数的情况,对于二分到的步数先均分给四个边,因为是偶数,%4一定是2或0了,如果余2 那么我就可以使两个对边长度在增加1 ,这时的面积为 ch *ku *2. 然后我发现对于步数比他多1的奇数来说,他所能得到的面积正是在原来的四边形上在多扩展一个等腰梯形,且步数正好多1.所以我check就判断了奇数和偶数来check了,
至于为什么是一定多一步的,从最后一个样例5为7可以看出来为什么,然后多画几个结论就得到了.
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int maxn = 1e5 + 10;typedef long long ll;ll n;int check(ll x){ ll res = x; if(x & 1) res --; ll len = res / 4; ll ch ,ku; ch = ku = len; if(res % 4) ch++; ll s = 0; if(x % 2 == 0) { s = ch * ku * 2; } else { double ss = 0.5 * (2*ch - 1); // cout<<x<<' '<<ss<<endl; s = ch * ku * 2 + (ll)ss; //cout<<s<<endl; } if(s >= n) return 1; return 0;}int main(){ int t; cin>>t; while(t--) { scanf("%lld",&n); ll l = 0,r = 2*1e9,mid,ans; while(l <= r) { mid = (l + r) >> 1; if(check(mid)) r = mid - 1,ans = mid; else l = mid + 1; } //check(7);// puts("");// check(6); printf("%lld\n",ans); } return 0;}
hdu 6156 && 1007 Palindrome Function
2 -36 进制中 (L,R ) 回文数有多少个
让你求(l,r)满足条件的数有多少啊..这不很明显数位dp,算了复杂度,足够了.枚举每种进制,剩下的求法和10进制回文数有多少一样了.
我这里dp【i】【j】【k】【f】表示的是k进制下,串的起点是i,终点是j, 是否已经是回文串了.f 为0 表示否 1 表示 是
PS: 这里需要注意的就是前导0的问题,由于前导0的存在使得回文串的长度是不固定的,所以这里就设法解决前导0就好,另外需要开个中间数组记录一下前面填过的数,来判断回文
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int maxn = 1e5 + 10;typedef long long ll;ll dp[50][50][50][5];// dp【i】【j】【k】【f】表示的是k进制下,串的起点是i,终点是j,// 是否已经是回文串了. f 为0 表示否 1 表示 是 int num[50],temp[50];//temp 中间数组 ,用来判断回文 ll dfs(int start,int cur,int state,int fp,int base)//start 字符串起点,也用来确定第一个非前导0的位置.cur 当前处理到第几位//state 是否是回文串.// base 进制 { if(cur<0) return state; if(!fp&&dp[start][cur][base][state]!=-1) return dp[start][cur][base][state]; int fpmax = fp ? num[cur] : (base-1); ll ret = 0; for(int i = 0;i <= fpmax;i++) { temp[cur] = i;//确定该位的值 if(start == cur&&i == 0)// 前导0 ret+=dfs(start-1,cur-1,state,fp && i == fpmax,base); else if(state&&cur<(start+1)/2)//小于一半了,说明要开始判断是否回文了 ret+=dfs(start,cur-1,temp[start-cur]==i,fp&&i==fpmax,base); else//未构成回文串就继续处理下一位. ret+=dfs(start,cur-1,state,fp&&i==fpmax,base); } if(!fp) dp[start][cur][base][state]=ret; return ret;}ll solve(ll n,int k){ int len=0; while(n) { num[len++]=n%k; n/=k; } num[len]=0; return dfs(len-1,len-1,1,1,k);}int main(){ int _; cin>>_; ll L,R; int l,r; ll ans1,ans2,ans,ans3; int t=1; memset(dp,-1,sizeof dp); while(_--) { ans = 0; scanf("%lld %lld %d %d",&L,&R,&l,&r); for(int i = l;i <= r;i++) { ans1 = solve(L-1,i); ans2 = solve(R,i); ans3 = ans2 - ans1; ans += ans3*i + (R - L + 1 - ans3); } printf("Case #%d: %lld\n",t++,ans); } return 0;}
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 【HDU6150 2017中国大学生程序设计竞赛
- 【HDU6152 2017中国大学生程序设计竞赛
- 【HDU6153 2017中国大学生程序设计竞赛
- 《Unix网络编程》卷1:套接字联网API(第3版):守护进程和inetd超级服务器、高级I/O、Unix域协议
- 第三篇:设计模式六大原则: 一个萝卜一个坑 -- 单一职责原则
- C++11:线程
- Tomcat的使用(详细流程)
- [LintCode]8.旋转字符串
- 2017中国大学生程序设计竞赛
- Java I/O流复习(一)—File类、字节流、字节缓冲流
- NXP LPC54110试用体验2:在keil中使用J-LINK烧录环境搭建篇
- 摄影口诀--针对不同情景
- pywin32不能安装如何解决
- 一步步写STM32 OS【三】PendSV与堆栈操作
- 跳动的心
- 第四篇:设计模式六大原则: 一国两制 -- 开放封闭原则
- C++学习之路(8)---Qt学习—qt共享内存的使用