记录洛谷刷题C语言QAQ
[USACO22JAN] Herdle B
题目描述
奶牛们发明了一种名为 Herdle 的新型解谜游戏,在牛界引起了轰动。
每天都会有一个新谜题发布供奶牛解决。游戏采用 3 × 3 3\times 3 3×3 方阵的形式表示农场的一块田地,田地的每个方格都由特定品种的奶牛占据。总共只有 26 26 26 种可能的品种,每一种由 A \text{A} A 到 Z \text{Z} Z 中的不同大写字母标识。玩家不会被告知田地中的奶牛品种排列方式——游戏目标是通过一系列猜测确定它们。
每次猜测,奶牛们输入一个 3 × 3 3\times 3 3×3 的大写字母方阵,表示该田地可以用奶牛填充的可能方式。猜测的某些方格可能是正确的。这些方格以绿色高亮显示,让奶牛们知道这些是正确的。猜测的另一些方格可能填入了品种正确但位置错误的奶牛。这些以黄色高亮显示。
黄色高亮显示的方格的数量可以帮助指示某个品种的奶牛数量。 例如,假设猜测方阵包含 4 4 4 头品种 A \text{A} A 的奶牛,而答案方阵包含 2 2 2 只品种 A \text{A} A 的奶牛,其中没有正确位置上的 A \text{A} A (即,它们都不应该是绿色的)。 在这种情况下,猜测方阵中只有两个 A \text{A} A 应以黄色高亮显示。 更准确地说,如果猜测方阵中有 x x x 个特定品种的奶牛,并且 答案方阵中有 y ≤ x y \le x y≤x 头该品种奶牛(不包括位置正确而得到绿色高亮显示的奶牛),那么猜测方阵的 x x x 头奶牛中只有 y y y 头奶牛应该以黄色高亮显示。
给定正确答案的方阵和一个表示对该答案的猜测的方阵,请计算绿色和黄色高亮显示的方格的数量。
输入格式
输入的前 3 行给定了正确答案的方阵。以下 3 行表示对该答案的猜测。
输出格式
输出两行。输出的第一行包含应当以绿色高亮显示的方格的数量。输出的第二行包含应当以黄色高亮显示的方格的数量。
样例 #1
样例输入 #1
COW
SAY
MOO
WIN
THE
IOI
样例输出 #1
1
1
样例 #2
样例输入 #2
AAA
BBB
CCC
AYY
AAA
ZZZ
样例输出 #2
1
2
提示
【样例解释 1】
在这个例子中,最后一行中间的 O 是正确的,所以这个方格以绿色高亮显示。字母 W 位于错误的位置,所以它以黄色高亮显示。
【样例解释 2】
在这里,其中一个 A 位于正确的位置,所以它以绿色高亮显示。余下的 A 均不在正确位置上,由于答案方阵中有两个 A,所以有两个 A 应当以黄色高亮显示。
代码如下:
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
int min(int a,int b){
if(a < b)
return a;
else
return b;
}
char a[4][4], b[4][4];
int green, yellow, rall[27], gall[27];
int main() {
char s;
for(int i = 1; i <= 3; i++)
{
for(int j = 1; j <= 3; j++)
{
scanf("%c",&a[i][j]);
}
s = getchar();
}
for(int i = 1; i <= 3; i++)
{
for(int j = 1; j <= 3; j++)
{
scanf("%c",&b[i][j]);
}
s = getchar();
}
for(int i = 1; i <= 3; i++)
for(int j = 1; j <= 3; j++)
if(a[i][j] == b[i][j]) green++;
else {
rall[a[i][j] - 'A' + 1]++;
gall[b[i][j] - 'A' + 1]++;
}
for(int i = 1; i <= 26; i++)
yellow += min(rall[i], gall[i]);
printf("%d\n%d\n", green, yellow);
return 0;
}
[USACO22JAN] Non-Transitive Dice B
题目描述
为了消磨牛棚里的时光,奶牛们喜欢玩简单的骰子游戏。其中一种游戏使用两个骰子 X 和 Y 进行。两个骰子均被投掷,获胜的骰子是显示的数字较大的骰子。如果两者显示相同的数字,则重新投掷(只要持续打平,骰子可能会被重新投掷多次)。我们称骰子 X 击败骰子 Y,如果骰子 X 比骰子 Y 更有可能赢得这局游戏。
考虑以下的 4 4 4 面骰子:
骰子 A 在各面上有数字 4 4 4, 5 5 5, 6 6 6 和 7 7 7。
骰子 B 在各面上有数字 2 2 2, 4 4 4, 5 5 5 和 10 10 10。
骰子 C 在各面上有数字 1 1 1, 4 4 4, 8 8 8 和 9 9 9。
这些骰子满足一个相当奇妙的性质:A 击败 B,B 击败 C,并且 C 也击败 A。特别地,三个骰子都不是「最佳的」,可以击败其他两个。在这种情况下,当没有两个骰子打平,也没有一个骰子是最佳的,我们称这三个骰子的集合为「非传递的」。在非传递的三个骰子的集合中,每个骰子击败一个其他骰子,并输给另一个其他骰子。
给定两个 4 4 4 面骰子 A 和 B 各面上的数字,请帮助奶牛们求出是否有方法为第三个骰子 C 的各面分配数字,使得这个骰子的集合是非传递的。所有骰子面上的数字必须是 1 1 1 到 10 10 10 的整数。
输入格式
每个测试用例包含多个独立的子测试用例,必须全部回答正确才能通过整个测试用例。输入的第一行包含 T T T( 1 ≤ T ≤ 10 1\le T\le 10 1≤T≤10),为你需要求解的子测试用例的数量。
以下 T T T 行,每行描述了一个子测试用例,包含 8 8 8 个整数:骰子 A 的 4 4 4 面上的整数,以及骰子 B 的 4 4 4 面上的整数。所有的数均在 1 1 1 到 10 10 10 之间,不一定排序。可能同一个数会出现多次,即使在同一个骰子上也可能出现多个相同的数。
输出格式
输出
T
T
T 行。如果有可能为骰子 C 分配数字使得第
k
k
k 个测试用例成为一个非传递的骰子集合,则第
k
k
k 行输出 yes
,否则输出 no
。
样例 #1
样例输入 #1
3
4 5 6 7 2 4 5 10
2 2 2 2 1 1 1 1
1 1 1 1 2 2 2 2
样例输出 #1
yes
no
no
提示
【样例解释】
第一个子测试用例对应题目中的例子。在第二个子测试用例中,不存在骰子 C 可以使得这个骰子集合是非传递的。同理第三个子测试用例的答案也是 no
。
代码如下:
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
int T;
int a[5];
int b[5];
int c[5];
int main(){
scanf("%d",&T);
while(T--){
for(int i=1;i<=4;i++) scanf("%d",&a[i]);
for(int i=1;i<=4;i++) scanf("%d",&b[i]);
int win=0,lose=0;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
if(a[i]>b[j]) win++;
else if(a[i]<b[j]) lose++;
if(win==lose){ //处理打平
printf("no\n");
continue;
}
int flag=0;
for(int i = 1;i < 5;i++)
{
for(int j = i +1;j < 5;j++)
{
if(a[i] < a[j])
{
a[i] = a[i] + a[j];
a[j] = a[i] - a[j];
a[i] = a[i] - a[j];
}
if(b[i] < b[j])
{
b[i] = b[i] + b[j];
b[j] = b[i] - b[j];
b[i] = b[i] - b[j];
}
}
}
if(win<lose)
{
a[4] = a[4] + b[4];
b[4] = a[4] - b[4];
a[4] = a[4] - b[4];
a[1] = a[1] + b[1];
b[1] = a[1] - b[1];
a[1] = a[1] - b[1];
a[2] = a[2] + b[2];
b[2] = a[2] - b[2];
a[2] = a[2] - b[2];
a[3] = a[3] + b[3];
b[3] = a[3] - b[3];
a[3] = a[3] - b[3];
}
for(c[1]=1;c[1]<=10;c[1]++){
for(c[2]=c[1];c[2]<=10;c[2]++){
for(c[3]=c[2];c[3]<=10;c[3]++){
for(c[4]=c[3];c[4]<=10;c[4]++){
int f1=1;
int w1=0,l1=0,w2=0,l2=0;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++){
if(a[i]>c[j]) w1++;
else if(a[i]<c[j]) l1++;
if(b[i]>c[j]) w2++;
else if(b[i]<c[j]) l2++;
}
if(w1<l1&&w2>l2){
printf("yes\n");
flag=1;
break;
}
}
if(flag) break;
}
if(flag) break;
}
if(flag) break;
}
if(!flag) printf("no\n");
}
return 0;
}
「PMOI-5」破译の论
题目背景
2077 年,穿越的 Lanuxhem 为与 2021 年的 Silver187 联系,发明了一种图形转数字的密码。
题目描述
lhm 现在有一个边长为 1 1 1 的正方形,现在要进行 k k k 次分割,每次分割需要把位于图形中右下角的矩形继续分割成 n × n n \times n n×n 的矩形。分割完成后所有矩形的个数即为破译后的答案。lhm 需要聪明的你帮助他解决这个问题。
注:由于题面形容比较困难,请移步至样例解释便于理解题意。
输入格式
输入数据共一行。
一行两个整数
n
,
k
n,k
n,k,含义如题目所示。
输出格式
输出格式共一行。
一行一个整数,表示最终答案。
由于答案可能过大,请把答案取模
998244353
998244353
998244353 后输出。
样例 #1
样例输入 #1
2 2
样例输出 #1
7
样例 #2
样例输入 #2
5 3
样例输出 #2
73
提示
样例解释
对于样例 #1,进行 2 2 2 次分割,每次将右下角矩形分割为 2 × 2 2\times 2 2×2 的矩形。
第一次分割,由于只有一个矩形,所以右下角矩形即为此矩形。分割前后如下:
变为
接下来进行第二次分割,将右下角矩形进行分割,分割为如下图形:
此图形包含 7 7 7 个矩形,因此答案为 7 7 7。
数据规模与约定
对于
10
%
10\%
10% 的数据,
k
=
1
k=1
k=1。
对于另
20
%
20\%
20% 的数据,
1
≤
n
,
k
≤
10
1 \leq n,k \leq 10
1≤n,k≤10。
对于
100
%
100\%
100% 的数据,
1
≤
n
,
k
≤
1
0
9
1 \leq n,k \leq 10^9
1≤n,k≤109。
2022.7.10 2022.7.10 2022.7.10:新增加一组 Hack \text{Hack} Hack 数据。
代码如下:
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
long long ksc(long long a, long long b, long long c) {
if (! b) return 0;
long long ans = ksc(a, b >> 1, c);
ans = (ans + ans) % c;
if (b & 1) ans = (ans + a) % c;
return ans;
}
signed main() {
long long n, k;
scanf ("%lld%lld", &n, &k);
long long ans = 1 + ksc(n * n - 1, k, 998244353);
ans = ans % 998244353;
printf ("%lld", ans);
return 0;
}
小智的疑惑
题目描述
传智专修学院给了小智一个仅包含小写字母的字符串
s
s
s,他想知道,里面出现了多少次子串 chuanzhi
呢。
我们称一个字符串
t
t
t 是
s
s
s 的子串,当且仅当将
s
s
s 的开头若干个(可以为 0 个)连续字符和结尾若干个(可以为 0 个)连续字符删去后,剩下的字符串和
t
t
t 相同。例如,我们称 ab
是 abc
的子串,但 ac
不是 abc
的子串。
输入格式
输入只有一行一个字符串,表示字符串 s s s。
输出格式
输出一行一个整数表示答案。
样例 #1
样例输入 #1
welcometochuanzhicupchuanzhi
样例输出 #1
2
提示
数据规模与约定
对于全部的测试点,保证 1 ≤ ∣ s ∣ ≤ 4 × 1 0 5 1 \leq |s| \leq 4 \times 10^5 1≤∣s∣≤4×105, ∣ s ∣ |s| ∣s∣ 表示 s s s 的长度,且 s s s 中只有小写字母。
代码如下:
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
int main(){
char ch[400005];
scanf("%s",ch+1);
int len=strlen(ch+1);//长度
int ans=0;//计数器
for(int i=1;i<=len;i++){
if(ch[i]=='c'&&ch[i+1]=='h'&&ch[i+2]=='u'&&ch[i+3]=='a'&&ch[i+4]=='n'&&ch[i+5]=='z'&&ch[i+6]=='h'&&ch[i+7]=='i'){//判断是否符合题意
ans++;
}
}
printf("%d",ans);
}
三元组
题目描述
给定一个长度为 n n n 的数列 a a a,对于一个有序整数三元组 ( i , j , k ) (i, j, k) (i,j,k),若其满足 1 ≤ i ≤ j ≤ k ≤ n 1 \leq i \leq j \leq k \leq n 1≤i≤j≤k≤n 并且 a i + a j = a k a_i +a_j = a_k ai+aj=ak,则我们称这个三元组是「传智的」。
现在请你计算,有多少有序整数三元组是传智的。
输入格式
本题单测试点内有多组测试数据。
输入的第一行是一个整数 T T T,表示数据组数。
对于每组数据:
第一行是一个整数,表示数列的长度
n
n
n。
第二行有
n
n
n 个整数,第
i
i
i 个整数表示
a
i
a_i
ai。
输出格式
对于每组数据,输出一行一个整数表示答案。
样例 #1
样例输入 #1
2
3
1 2 3
5
1 2 3 4 5
样例输出 #1
2
6
提示
样例 1 解释
对于第一组数据,因为
a
1
+
a
1
=
a
2
a_1 + a_1 = a_2
a1+a1=a2,
a
1
+
a
2
=
a
3
a_1 + a_2 = a_3
a1+a2=a3,故共
(
1
,
1
,
2
)
(1, 1, 2)
(1,1,2) 和
(
1
,
2
,
3
)
(1, 2, 3)
(1,2,3) 两个三元组。
对于第二组数据六个三元组分别是:
- ( 1 , 1 , 2 ) (1, 1, 2) (1,1,2)
- ( 1 , 2 , 3 ) (1, 2, 3) (1,2,3)
- ( 1 , 3 , 4 ) (1, 3, 4) (1,3,4)
- ( 1 , 4 , 5 ) (1, 4, 5) (1,4,5)
- ( 2 , 2 , 4 ) (2, 2, 4) (2,2,4)
- ( 2 , 3 , 5 ) (2, 3, 5) (2,3,5)
数据规模与约定
对于全部测试点,保证 1 ≤ T ≤ 100 1 \leq T \leq 100 1≤T≤100, 1 ≤ n , a i ≤ 100 1 \leq n , a_i \leq 100 1≤n,ai≤100,且各个测试点的 n n n 之和不超过 100 100 100,即 ∑ n ≤ 100 \sum n \leq 100 ∑n≤100。
代码如下:
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
int n,a[105];
int main()
{
scanf("%d",&n);
while(n--){
int m,sum=0;
scanf("%d",&m);
for(int i = 1;i <= m;i++)
scanf("%d",&a[i]);
for(int i = 1;i <= m;i++)
for(int j = i;j <= m;j++)
for(int k = j;k <= m;k++)
if(a[i]+a[j]==a[k])
sum++;
printf("%d\n",sum);
}
return 0;
}