BestCoder Round 75
题目链接:传送门
HDU 5640-5644
题目描述是复制的,有些乱码,大致意思能看懂。
King's Cake
Accepts: 960
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
阅兵式前一天,是国王的生日,大臣们为他准备了一个 n \times m(1\le n, m \le 10000)n×m(1≤n,m≤10000) 的蛋糕。他准备切蛋糕,但他切蛋糕有奇奇怪怪的癖好,他每次只切一刀,切下一个正方形蛋糕。请问它最多能切出多少个正方形蛋糕?
输入描述
第一行一个整数表示测试组数:T(0 < T\le1000)T(0<T≤1000) 。
每组数据占一行,每行两个整数 n \times m(1\le n, m \le 10000)n×m(1≤n,m≤10000),表示蛋糕的大小。
输出描述
共 TT 行,每行一个整数表示最多能切出的正方形蛋糕数量。
输入样例
2 2 3 2 5
输出样例
3 4
Hint
对于第一组数据,可切出一个 2\times22×2, 两个 1\times 11×1,共 33 个。
对于第一组数据,可切出两个 2\times22×2, 两个 1\times 11×1,共 44 个。
#include <iostream> #include <math.h> #include <stdio.h> using namespace std; int main() { int t,n,m,a,ans=0; cin>>t; while(t--) { ans=0; cin>>n>>m; if(n>m) swap(n,m); while(m%n) { ans+=m/n; a=n; n=m%n; m=a; } ans+=m/n; cout<<ans<<endl; } return 0; }
King's Phone
Accepts: 310
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
阅兵式上,国王见到了很多新奇东西,包括一台安卓手机。他很快对手机的图形解锁产生了兴趣。
解锁界面是一个 3 \times 33×3 的正方形点阵,第一行的三个点标号 1, 2, 31,2,3,第二行的三个点标号 4, 5, 64,5,6,第三行的三个点标号 7, 8, 97,8,9。密码本身是一段序列,表示经过点的先后顺序,但遵循如下规则:
1. 密码至少经过四个点。
2. 不能重复经过同一个点。
3. 路径上的中间点不能跳过,除非已经被经过(34273427 是合法的,但 37243724 不合法)。
他想设置的密码的长度为正整数 k(1\le k\le 9)k(1≤k≤9),密码序列为 s_1 s_2...s_k(0\le s_i < INT\_MAX)s1s2...sk(0≤si<INT_MAX),他想知道这个密码序列是否合法,这个问题交给了你。
输入描述
第一行一个整数表示测试组数:T(0 < T\le100000)T(0<T≤100000) 。
每组数据占一行,每行第一个数 kk,设置密码的长度;接着 kk 个正整数,之间用空格隔开,表示密码序列 s_1s_2...s_ks1s2...sk。
输出描述
共 TT 行。对每组数据,若合法输出 `valid`,否则输出 `invalid`。
输入样例
3 4 1 3 6 2 4 6 2 1 3 4 8 1 6 7
输出样例
invalid valid valid
Hint
对于第一组数据,11 到 33 跳过了路径上的点 22,所以不合法。
对于第二组数据,11 到 33 时点 22 已经被经过了,所以合法。
对于第三组数据,8\rightarrow 1 \rightarrow 6 \rightarrow 78→1→6→7 路径均没有中间点,所以合法。
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; int vis[15]; int judge(int a,int b) { if(a>b) swap(a,b); int c=b-a; if(c==2&&(a==1||a==4||a==7)&&!vis[(a+b)/2]) return 0; if(c==4&&a==3&&!vis[(a+b)/2]) return 0; //这里注意运算符运算顺序 逻辑与高于逻辑或 加括号 if((c==6||c==8)&&!vis[(a+b)/2]) return 0; return 1; } int main() { int t,k,a[15]; scanf("%d",&t); while(t--) { scanf("%d",&k); int flag=1; if(k<4||k>9) flag=0; for(int i=0; i<k; i++) { scanf("%d",&a[i]); if(a[i]<1||a[i]>9) flag=0; } if(flag==0) { puts("invalid"); continue; } memset(vis,0,sizeof(vis)); vis[a[0]]=1; for(int i=1; i<k; i++) { vis[a[i]]++; if(!judge(a[i],a[i-1])||vis[a[i]]>1) flag=0; //if(!judge(a[i],a[i-1])) printf("%d\n",i); } if(flag) puts("valid"); else puts("invalid"); } return 0; }
King's Order
Accepts: 381
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
国王演讲后士气大增,但此时战争还没有结束,国王时不时要下发命令。
由于国王的口吃并没有治愈,所以传令中可能出现:“让第三军-军-军,到前线去” 这样的命令。由于大洋国在军队中安插了间谍 , 战事紧急,很多时候前线的指挥官不能分清哪些命令真正来自国王。但国王的命令有一个特点,他每次连续重复的字符最多 33 次. 所以说他的命令中没有:“让第三军-军-军-军 , 到前线去”,但是可以有 :“让第三军-军 , 到前线去” 。
此时将军找到了你,你需要告诉他,给定命令的长度长度为 nn,有多少种不同的命令可以是国王发出的 。(也就是求长度为 nn 的合格字符串的个数)当然,国王可能说出一句话没有犯任何口吃,就像他那次演讲一样。
为了简化答案,国王的命令中只含有小写英文字母,且对答案输出模 10000000071000000007。
我们认为两个命令如果完全相同那么这两个字符串逐个比较就完全相同。
输入描述
第一行一个整数表示测试组数:T(T \le10)T(T≤10)。
每组数据占一行,每行一个正整数 n(n \le 2000)n(n≤2000) 表示字符串的长度。
输出描述
共 TT 行,每行一个整数表示合法的命令数量。
输入样例
2 2 4
输出样例
676 456950
Hint
两个中没有不符合要求的,所以答案为 26\times 26 = 67626×26=676 四个不符合要求的只有 `aaaa` `bbbb` ... `zzzz`总共 26 个 那么答案就是: 26^4-26 = 456950264−26=456950
这个题可以看做是数位DP:传送门。看成是斜着向右下传递。
也可以用递推做,a[i]=(a[i-1]+a[i-2]+a[i-3])*25;
a[i-k]表示结尾有长度为k个相同字符的序列,比如当i=4的时候 k=1,2,3就分别对应着数位DP中的dp[i][k]。
口口口C
口口CC
口CCC
就是这个意思。
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; typedef long long ll; const ll mod=1e9+7; ll a[2005]; void get() { memset(a,0,sizeof(a)); for(int i=0; i<4; i++) { if(i>0) a[i]=a[i-1]*26; else a[i]=1; } for(int i=4; i<=2000;i++) a[i]=(a[i-1]+a[i-2]+a[i-3])*25%mod; } int main() { get(); int t,n; scanf("%d",&t); while(t--) { scanf("%d",&n); printf("%lld\n",a[n]); } return 0; }
King's Game
Accepts: 249
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
为了铭记历史,国王准备在阅兵的间隙玩约瑟夫游戏。它召来了 n(1\le n\le 5000)n(1≤n≤5000) 个士兵,逆时针围成一个圈,依次标号 1, 2, 3 ... n1,2,3...n。
第一轮第一个人从 11 开始报数,报到 11 就停止且报到 11 的这个人出局。
第二轮从上一轮出局的人的下一个人开始从 11 报数,报到 22 就停止且报到 22 的这个人出局。
第三轮从上一轮出局的人的下一个人开始从 11 报数,报到 33 就停止且报到 33 的这个人出局。
第 n - 1n−1 轮从上一轮出局的人的下一个人开始从 11 报数,报到 n - 1n−1 就停止且报到 n - 1n−1 的这个人出局。
最后剩余的人是幸存者,请问这个人的标号是多少?
输入描述
第一行一个整数表示测试组数:T(0 < T\le5000)T(0<T≤5000) 。
每组数据占一行,包含一个整数 nn,表示 nn 个人围成一圈。
输出描述
共 TT 行。对每组数据,输出幸存者的编号。
输入样例
2 2 3
输出样例
2 2
Hint
对于第一组数据,一开始报到 11 的人即标号为 11 的人退出,幸存者是 22 号。
对于第二组数据,一开始报到 11 的人即标号 11 的人退出。接着 22 号报 11,33 号报 22,报到 22 的人即 33 号退出。幸存者是 22 号。
约瑟夫环的简单变形,注意是从终态向始态递推,附上一个约瑟夫环的链接:传送门。
#include <cstdio> #include <iostream> using namespace std; int main() { int ans,n,k,t; scanf("%d",&t); while(t--) { scanf("%d",&n); ans=0; //分析过程 约瑟夫环下标要倒着加回来 所以先加n-1再依次加n-2 //i只是取余用的 实际上是从干掉最后一个人一直递归到干掉一个人之前的状态 //所以是先加大的 最后加小的 for(int i=2;i<=n;i++) ans=(ans+((n+1)-i))%i; printf("%d\n",ans+1); } return 0; }