BestCoder Round #74
来源:互联网 发布:vue vendor.js 编辑:程序博客网 时间:2024/05/19 19:13
http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=675
1001 - King’s Cake
显然这很像求最大公约数的过程嘛,看这张神图:
http://bestcoder.hdu.edu.cn/images/solution/677-1.gif
所以每次 gcd\gcdgcd 的时候累加答案即可,复杂度 O(logmax(n,m)T)O(\log\max(n, m)T)O(logmax(n,m)T)。
当然你要是循环减应该也放过了。
#include<iostream>#include<stdio.h>using namespace std;int T;int n,m;int ans=0;void solve(int a,int b){ if(a<b) swap(a,b); if(b==0) return ; ans+=a/b; a%=b; solve(a,b);}int main(){ scanf("%d",&T); while(T--) { ans=0; scanf("%d%d",&n,&m); solve(n,m); printf("%d\n",ans); }}
1002 - King‘s Phone
一个简单的模拟题,首先判断序列长度是否合法,接着判断 sis_isi 是否在 [1,9][1, 9][1,9],最后扫一遍看看有没有重复以及跨过中间点的情况即可。
复杂度:O(nT)O(nT)O(nT)。
#include<iostream>#include<stdio.h>using namespace std;int T;int n;int vis[10];int a[10];bool OK(){ for(int i=1;i<=n;i++) { int aa=a[i],bb=a[i+1]; if(vis[aa]==1) return 0; if(i==n) return 1; vis[aa]=1; if(aa>bb) swap(aa,bb); if(bb==aa+1) continue; if(aa%3==1&&bb==aa+2) if(!vis[aa+1]) return 0; if(aa==1&&bb==9) if(!vis[5]) return 0; if(aa==3&&bb==7) if(!vis[5]) return 0; if(aa<=3&&bb==aa+6) if(!vis[aa+3]) return 0; } return 1;}int main(){ scanf("%d",&T); while(T--) { int flag=0; scanf("%d",&n); for(int i=1;i<=10;i++) vis[i]=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]<=0||a[i]>9) flag=1; } if(n>=10||n<4||flag==1) printf("invalid\n"); else { if(!OK()) printf("invalid\n"); else printf("valid\n"); } }}
1003 - King’s Order
数一个长度为 nnn 的序列 , 并且序列中不能出现长度大于 333 的连续的相同的字符 , 这玩意就是一个数位DP嘛。 定义 d[i][j][k]d[i][j][k]d[i][j][k] 为处理完 iii 个字符 , 结尾字符为 ′a′+j’a’+j′a′+j , 结尾部分已重复出现了 kkk 次的方案数。 刷表转移一下就好啦。
复杂度:O(26∗26∗nT)O(26 * 26 * nT)O(26∗26∗nT)
1004 - King’s Game
约瑟夫问题的一个变种,然而题目全部是在唬人,就是一个简单的递推。虽然我知道有人会打表。。。
我们看看裸的约瑟夫是怎么玩的:nnn 个人,每隔 kkk 个删除。
由于我们只关心最后一个被删除的人,并不关心最后的过程,所以,我们没有必要也不能够模拟整个过程。我们用递推解决。假设有nnn个人围成环,标号为[0,n−1][0,n-1][0,n−1]从000开始的好处是取模方便),每数kkk个人杀一个的情况下,最后一个存活的人的编号是f[n]f[n]f[n]。
我们有f[1]=0f[1]=0f[1]=0,这不需要解释。
接着考虑一般情况f[n]f[n]f[n],第一个杀死的人的编号是k−1k-1k−1,杀死后只剩下n−1n-1n−1个人了,那么我们重新编号!
原来编号为k的现在是000号,也就是编号之间相差333我们只要知道现在n−1n-1n−1个人的情况最后是谁幸存也就知道nnn个人的情况是谁幸存。幸运的是f[n−1]f[n-1]f[n−1]已经算出来了那f[n]f[n]f[n]就是在f[n−1]f[n-1]f[n−1]的基础上加上一个kkk即可不要忘记总是要取模。
http://bestcoder.hdu.edu.cn/images/solution/677-2.png
所以递推式子是: f[i]={ 0 i=1 (f[i - 1] + k) mod i otherf[i] =
此题只用在原版约瑟夫问题上加一维,由于依次隔 1,2,3…n−11, 2, 3…n - 11,2,3…n−1 个人删除,所以用 f[i][j]f[i][j]f[i][j] 表示 iii 个人,依次隔 j,j+1…j+i−1j, j + 1… j + i - 1j,j+1…j+i−1 个人的幸存者标号。
根据刚才的重标号法,第一次 j−1j - 1j−1 号出局,从 jjj 开始新的一轮,从 j+1j + 1j+1 开始清除,剩余 i−1i - 1i−1 个人,也有递推式子:
f[i][j]={ 0 i=1 (f[i - 1][j+1] + j) mod i otherf[i][j] =
答案就是 f[n][1]+1f[n][1] + 1f[n][1]+1(将标号转移到 [1,n][1, n][1,n]),问题轻松解决。
复杂度:预处理 O(n2)O(n^2)O(n2),查询 O(1)O(1)O(1),总复杂度 O(n2)O(n^2)O(n2)。由于可以滚动数组以及常数太小,所以 nnn 给了 500050005000(其实是出题人不会别的算法嘿嘿嘿)。
#include<iostream>#include<stdio.h>using namespace std;int T;int n;int main(){ scanf("%d",&T); while(T--) { scanf("%d",&n); int f=0; for(int i=2;i<=n;i++) f=(f+n-i+1)%i; f=(f+1)%n; if(f<=0) f+=n; printf("%d\n",f); }}
- BestCoder Round #74
- BestCoder Round #74
- BestCoder Round #74
- BestCoder Round #74 (div.2)
- BestCoder Round #74 Shortest Path
- hdu 5637 BestCoder Round #74 (div.2)
- hdu5635 BestCoder Round #74 (div.2)
- BestCoder Round #74 (div.2) LCP Array
- BestCoder Round #74 HDU 5638 Topsort
- BestCoder Round #74 (div.2)【1排列组合】
- BestCoder Round #3 BestCoder Sequence
- bestcoder round #1
- BestCoder round #1
- BestCoder Round #1
- 【索引】BestCoder Round #2
- BestCoder Round #2
- 【索引】BestCoder Round #3
- BestCoder Round #3
- java并发编程基础之线程安全
- acm 1000 Moving Tables(贪心算法)
- k--Means
- GitHub 版本配置 详细教程
- Spark Executor Driver资源调度小结
- BestCoder Round #74
- Java异常相关的面试题(上)
- 答答租车系统
- [DIV/CSS] 用CSS和JS打造一个简单的图片编辑器
- eclipse 连接 cdh5.5 插件
- 动态加载Dll时,通过Type生成类对象
- 递归实现字符串反向输入
- js中报错:$ is not defined
- 谁将会参加比赛的问题(java 实现)