A题:
没啥好讲的 挺清晰的一道题
#include<iostream>
#include<cstring>
int main()
{
using namespace std;
char a[13][4]={"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};//这里用二维数组存
int T;
cin>>T;
while(T--)
{
char b[4][3];
cin>>b[0]>>b[1]>>b[2];
bool flag=false;
for(int i=0;i<12;++i)
{
if(strcmp(a[i],b[0])==0&&strcmp(a[(i+4)%12],b[1])==0&&strcmp(a[(i+7)%12],b[2])==0)
{
flag=true;
cout<<"Major triad"<<endl;
break;
}
else if(strcmp(a[i],b[0])==0&&strcmp(a[(i+3)%12],b[1])==0&&strcmp(a[(i+7)%12],b[2])==0)
{
flag=true;
cout<<"Minor triad"<<endl;
break;
}
}
if(!flag)
cout<<"Dissonance"<<endl;
}
}
B题:
这题也是非常水的一道题目了 很快就去写了发现运行不了 以为是scanf不能这么用 反斜杠输不了之类的 所以马上就换方法写了 后面补题的时候发现可以这样的 就是换行符也会被读进去 与'h'不匹配 程序就运行不下去了
血亏 这么水的题 早该a了的
所以下次再遇到类似的要格式化输入字符串的情况 记得getchar()的使用
#include<iostream>
#include<cstdio>
#include<algorithm>
int main()
{
using namespace std;
int T;
cin>>T;
while(T--)
{
int n,k;
char a[50];
int b[1005];
cin>>n>>k;
for(int i=0;i<n;++i)
{
getchar();//★注意这里一定要加getchar()
scanf("http://acm.hit.edu.cn/problemset/%d",&b[i]);
}
sort(b,b+n);
for(int i=0;i<k-1;i++)
cout<<b[i]<<' ';
cout<<b[k-1]<<endl;
}
}
C题:
其实这题训练赛的时候想到大概思路了 但是没能往动态规划上面想 导致实现不了代码
下面是我现在自己的理解....可能会有些不对
这题好像就是..设一个二维数组dp[ i ][ j ] 表示主串前 j 位中能和子串前 i 位匹配的个数 然后下面子串外层循环 主串内层循环
如果没有匹配到相同字符:那么主串中前 j 位中能和子串前 i 位匹配的个数 就等于主串中前 j-1 位中能和子串前 i 位匹配的个数
在讲匹配到相同字符的情况前 先举个例子想一下 比如主串是eeettt 子串是et 当子串第一位(i=1)循环结束时,dp[1][3]是不是等于3(匹配到三个相等字符),当循环子串第二位 主串循环到第四位时 主串中前 j 位中能和子串前 i 位匹配的个数 即eeet中能和et匹配的个数 是不是等于eee中能和e匹配的个数 即=dp[ i-1 ][ j-1 ]=3
现在开始讨论 当匹配到相同字符时:如果子串循环到第一位 dp[ i ][ j ]就等于dp [ i ][ j-1 ]+1(主串前面能和子串第一位匹配的个数+1)
如果子串循环到后面 dp[ i ][ j ]=dp[ i-1 ][ j-1 ]+dp [ i ][ j-1 ](主串中前 j-1 位中能和子串前 i 位匹配的个数+主串中前j-1位能和子串前i-1位匹配的个数
#include<iostream>
#include<cstdio>
#include<cstring>
__int64 dp[1005][5005];//表示主串前j位中能和子串前i位匹配的个数
//dp太大了 必须要放在全局里
int main()
{
using namespace std;
const int mod=1e9+7;
char s[5005];
char t[1005];
scanf("%s%s",s+1,t+1);
//我觉得这里的+1好巧妙 之前一直不知道该怎么跳过第一位不存
int len1=strlen(t+1);
int len2=strlen(s+1);
memset(dp,0,sizeof(dp));//其实这里不用memset也可以 大概因为dp是全局数组吧
for(int i=1;i<=len1;++i)//子串
{
for(int j=1;j<=len2;++j)//主串
{
if(s[j]==t[i])//如果匹配到相等字符
{
if(i==1)
dp[i][j]=(1+dp[i][j-1])%mod;
else
dp[i][j]=(dp[i-1][j-1]+dp[i][j-1])%mod;//
}
else
dp[i][j]=dp[i][j-1];
}
}
cout<<dp[len1][len2]<<endl;
}
E题:
思维题 不过既然是思维题 自己写肯定是写不出了 但是这题我都能理解到 说明不是很难 可以好好看一看得
同样注意数据量过大不能用cin cout L题是队友写的 当时印象还没那么深刻 赛后补题的时候写这题一直TLE 很烦 后来跟那个L题队友抱怨的时候突然就一拍脑门 哦不能用cin啊!这回我一定再也忘不掉了
这题大概思路就是 找到一个最小值minn
如果只有一个最小值 那么这个值取余任何数都为这个最小值 即minn可以和与他相邻的所有数都进行操作变为minn(minn%x=minn) 最后就会只剩下minn 长度为1 所以其实计算出最小值个数cnt=1时可以直接输出长度为1 但是我的代码没有这么写
如果不止一个最小值 就要分情况讨论了
如果数组里的所有的数除了它本身 都是最小值minn的倍数:可以自己举几个例子试一下 因为最小值和其他的抵消之后 两个最小值相操作只能变成0 就不能继续操作了 所以最小值两两抵消 如果cnt是偶数 剩下的长度会是(cnt/2) 如果是奇数就需要再多加一个1了 其实就是向上取整的意思
如果有某个数x不是minn的倍数:minn可以和周围和他成倍数关系的全部抵消变成minn 当遇到某个数x不是minn的倍数 可以进行(x%minn)的操作 得到的数一定比minn还要小 我们又可以用这个比minn更小的值对其他所有数进行操作(这个值在数组里的个数一定只有一个)就会把其他所有的数都抵消掉 最后会只剩下这个数 因此长度为1
#include<iostream>
#include<cstdio>
__int64 a[1000010];//记得放全局
int main()
{
using namespace std;
int T;
cin>>T;
while(T--)
{
int minn=1e9+10;//初始化最小值
int n;
int cnt=0;//记录最小值的个数
cin>>n;//输入数组个数
for(int i=0;i<n;++i)
{
scanf("%d",&a[i]);
if(a[i]<minn)//如果找到更小的值
{
minn=a[i];//更新最小值
cnt=1;//重新计数
}
else if(a[i]==minn)//如果又有一个最小值
cnt++;//个数加一
}
bool flag=false;
for(int i=0;i<n;++i)
{
if(a[i]%minn!=0)//如果找到一个数不是最小值的倍数 可以直接跳出循环了 因为长度必然为1
{
flag=true;
break;
}
}
if(flag)
printf("1\n");
else
printf("%d\n",(cnt+1)/2);//向上取整 也可以用ceil函数
}
}
L题:
这题其实是挺水的一道题了 但是一直超时 反复看了很久 哪一个循环都是必不可少的 还很疑惑为什么别人一遍就能过了 最后突然醒悟是cin cout的问题 数据量过大一定要用printf scanf啊救命 这题错了得有七次吧 数不清的罚时了 谨记
#include<cstdio>
using namespace std;
long long aa[1000005];
int main()
{
long long a,c;
long long m;
scanf("%lld%lld%lld",&a,&m,&c);
long long t,i,t1,t2;
for(i=1;i<=a;i++)
scanf("%lld",&aa[i]);
while(c--)
{
scanf("%lld%lld",&t,&i);
t=aa[i]*t;
t1=t%m;
t2=t/m;
if(t2%2==0)
printf("%lld\n",t1);
else
printf("%lld\n",m-t1);
}
return 0;
}