日期:2023-10-04
学号:S12418
一:
总分数:40
T1【重复判断(repeat)】:0
T2【歪果仁学乘法(multiplication)】:40
T3【去重求和(summation)】:0
T4【点集操作(point)】:0
二、比赛过程
第一题低级错误
第二题考虑不周
第三题时间超限
第四题和没写差不多(
讽刺的是,考试结束自己测的T1T2立马全100了
(没错今天的情况和昨天几乎一模一样)
三、比赛分析
T【重复判断(repeat)】:
1、题目大意
给定两个字符串,判定a是否由完整的b构成。
2、比赛中的思考
借鉴了昨天不合法字符串那题的思路,还加了许多的特判
可是还是没对
3、解题思路
同昨天 当a[i]为b的结尾时,判断在之前b.size()个字符是否是b 不是就cout<<"NO"
4、AC代码
#include<iostream>
#include<string>
using namespace std;
int t;string a,kodori;
int main(){
cin>>t;
while(t--){
int flag = 1;
cin>>a>>kodori;
int n = (int)a.size();
a = " "+a;
for(int i = 1;i<=n;i+=kodori.size()){
if(a.substr(i,kodori.size()) !=kodori){
flag = false;
break;
}
}
if(flag == true){
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
return 0;
}
T2【歪果仁学乘法(multiplication)】:
1、题目大意
大水题
求出(a%10*b%10)+(a/10*b%10)+(a%10*b/10)+(a/10*b/10)的值
是个人都能对(
2、比赛中的思考
一眼野生大水题
想都没想就写了个for循环交上去了
喜提40pts
3、解题思路
就一行,即为上面表达式的值
4、AC代码(短到离谱)
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;cin>>a>>b;
cout<<(a%10*b%10)+(a/10*b%10)+(a%10*b/10)+(a/10*b/10)<<endl;
return 0;
}
T3【去重求和(summation)】:
1、题目大意
给定一个序列,让你求出Σ(n,l = 1)Σ(n,r = 1)sum(l,r)%1e9+7的值
(人话:对于所有可能的区间去重求和最后加一起)
2、比赛中的思考
三重循环,不出意料爆了
3、解题思路
说实话我也没彻底搞懂
首先输入
然后对于第一个出现的元素,将ta的mp设定为1
接下来(不是第一个)mp的值就是下标
干啥用呢?有大用
对于两个相同值之间的部分,可以视为一个块。对这个块套一下乘法原理,就可以得出当前块的ans
最后的最后,把ans累加起来即可
4、AC代码
#include<iostream>
#include<map>
#define ll long long
using namespace std;
map<int,int>mp;
ll n,a[10000007],ans,flag,l[10000007],r[10000007];
int main(){
cin>>n;
for(int i = 1;i<=n;i++){
cin>>a[i];
}
for(int i = 1;i<=n;i++){
l[i] = mp[a[i]]+1;
mp[a[i]] = i;
}
for(int i = 1;i<=n;i++){
ans+=1ll*a[i]*(i-l[i]+1)%1000000007*(n-i+1)%1000000007;
ans%=1000000007;
}
cout<<ans;
return 0;
}
T4【点集操作(point)】:
1、题目大意
给定一个有向图,把最大数量共同结点合并为一个,求合并后结点数。
2、比赛中的思考
别看我现在把题面写的这么简单,但是考试时我一点没明白
所以这题只能骗分 但一分没骗到
3、解题思路
链表具体实现,外加一手vector
通过特性来寻找(特性:第一个共同节点在一条链里出现过,在另一条链里也出现过)
所以我们将第一个寻找到的结点设为“代表”即可
只有出度的一定没法删掉,只有入度的一定会被删
最后输出次数,完成。
4、AC代码
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e6+5;
int n,m,x[N*2],y[N*2],in[N];
int head[N],ver[2*N],Next[2*N],tot = -1,ans;
bool b[N],vis[N];
vector<int>v;
void add(int x,int y){//链式前向星
ver[++tot]= y;
Next[tot] = head[x];
head[x] = tot;
}
int main(){
memset(head,-1,sizeof head);
cin>>n>>m;//n个点 m条边
for(int i = 1;i<=m;i++){//输入m条边
cin>>x[i]>>y[i];//输入x~y有一条有向边
add(x[i],y[i]);//链式前向星
in[y[i]]++;//统计入度
}
for(int i = 1;i<=n;i++){
if(!in[i]){//如果入度为零
v.push_back(i);//记录入度为零的点,最外层的点一定没法删
ans++;//没法删的点+1
}
}
for(int i = 1;i<=m;i++){
if(in[x[i]]){//x[i]不是第一层的点
b[y[i]] = 1;//标记层数>2的点
}
}
for(int i = 0;i<v.size();++i){//没有入度的最外层
for(int j = head[v[i]];~j;j = Next[j]){//第二层
int y = ver[j];//一定是第二层的点
if(!b[y]){//第二层的点又是>2层的点,不会进v,不用算,作为代表
b[y] = 1;
ans++;//合并后的新点标记
}
}
}
cout<<ans;
return 0;
}