题目来源:https://ac.nowcoder.com/acm/contest/87255
写在前面
今天的训练赛打的还行,发挥出我自己应有的水平,不过水平还是有限,该卡的地方还是卡着,有思路却写不出来是最难受的,还是得多刷刷题,提高代码水平
回归正题
按题目难度I、F、A、J、H、D、E顺序来展开
I- 重生之zbk要拿回属于他的一切
思路
签到题,暴力模拟即可
编程
void solve(){
int n;cin >> n;
string s;cin >> s;
if(n<5){
cout << 0 << endl;
return ;
}
string s1="chuan";
int sum=0;
for(int i=0;i<=s.size()-5;++i){
string s2=s.substr(i,5);
if(s2==s1) sum++;
}
cout << sum;
return ;
}
F-水灵灵的小学弟
思路
签到题,两人的缩写相同,直接输出DHY即可
编程
void solve(){
int a,b;
cin >> a >> b;
cout << "DHY" << endl;
return ;
}
A- 国际旅行Ⅰ
思路
签到题,将国家数量进行升序排序即可
编程
void solve(){
int n,m,q;
cin >> n >> m >> q;
for(int i=1;i<=n;++i) cin >> a[i];
for(int i=1;i<=m;++i){
int u,v;
cin >> u >> v;
}
sort(a+1,a+1+n);
while(q--){
int x;cin >> x;
cout << a[x] << endl;
}
return ;
}
J-这是签到
思路
暴力模拟,直接模拟1~5的行列式即可
编程
void solve(){
int n,m;
cin >> n >> m;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
cin >> a[i][j];
}
int minn=a[1][1];
if(n==1&&m==1){
cout << minn << endl;
return ;
}
int k=a[1][1]*a[2][2]-a[1][2]*a[2][1];
minn=min(k,minn);
if(n<=2&&m<=2){
cout << minn << endl;
return ;
}
int k1=a[1][1]*a[2][2]*a[3][3]+a[1][2]*a[2][3]*a[3][1]+a[1][3]*a[2][1]*a[3][2];
int k2=a[1][3]*a[2][2]*a[3][1]+a[1][1]*a[2][3]*a[3][2]+a[1][2]*a[2][1]*a[3][3];
minn=min(minn,k1-k2);
if(n<=3&&m<=3){
cout << minn << endl;
return ;
}
k1=a[1][1]*a[2][2]*a[3][3]*a[4][4]+a[1][2]*a[2][3]*a[3][4]*a[4][1]+a[1][4]*a[2][1]*a[3][2]*a[4][3]+a[1][3]*a[2][4]*a[3][1]*a[4][2];
k2=a[1][4]*a[2][3]*a[3][2]*a[4][1]+a[1][1]*a[2][4]*a[3][3]*a[4][2]+a[1][3]*a[2][2]*a[4][4]*a[3][1]+a[1][2]*a[2][1]*a[3][4]*a[4][3];
minn=min(minn,k1-k2);
if(n<=4&&m<=4){
cout << minn << endl;
return ;
}
k1=a[1][1]*a[2][2]*a[3][3]*a[4][4]*a[5][5]+a[1][2]*a[2][3]*a[3][4]*a[5][1]*a[4][5]+a[1][5]*a[2][1]*a[3][2]*a[4][3]*a[5][4]+a[1][3]*a[2][4]*a[3][5]*a[4][1]*a[5][2]+a[1][4]*a[2][5]*a[3][1]*a[4][2]*a[5][3];
k2=a[1][5]*a[2][4]*a[3][3]*a[4][2]*a[5][1]+a[1][1]*a[2][5]*a[3][4]*a[4][3]*a[5][2]+a[1][4]*a[2][3]*a[5][5]*a[3][2]*a[4][1]+a[1][2]*a[2][1]*a[3][5]*a[4][4]*a[5][3]+a[1][3]*a[2][2]*a[3][1]*a[4][5]*a[5][4];
minn=min(minn,k1-k2);
cout << minn << endl;
return ;
}
H-狼狼的备忘录
思路
考点:暴力模拟,用map套set存姓名和信息,每次存入信息时对当前信息和set里面的信息进行比对,判断当前信息是否可以插入进去以及判断set里面的信息是否应当被排出去(判断后缀即可),最后从头遍历map输出就行
编程
void solve(){
int n;cin >> n;
map<string,set<string>> m;//set为了去重
for(int i=0;i<n;++i){
string s;int q;
cin >> s >> q;
while(q--){
string x;cin >> x;
if(m[s].empty()) m[s].insert(x);
else{
int flag=1;//判断当前信息是否可以插入
vector<string> r;//需要被排出去的信息
for(auto t : m[s]){
if(t.size()>=x.size()){
int k=t.rfind(x);//必须反着找,正着找可能出现重复
if(k!=-1){
if(k+x.size()==t.size()) flag=0; //判断后缀
}
}
else{
int k=x.rfind(t);
if(k!=-1){
if(k+t.size()==x.size()) r.push_back(t);
}
}
}
if(flag) m[s].insert(x);
if(!r.empty()){
for(auto c : r) m[s].erase(c);
}
}
}
}
cout << m.size() << endl;
for(auto i : m){
cout << i.fi << " " << i.se.size() << " ";
for(auto j : i.se){
cout << j << " ";
}
cout << endl;
}
return ;
}
D-A*BBBB
思路
考点:模拟+前缀和维护
由于b的每一位都相同,将b的每一位拆分,可以将a * b看作a * b[0] + a * b[0] * 10 + a * b[0] * 100···
即每多一个b的个数,就将a*b[0]整体向左移动一位
这时我们可以考虑用前缀和,先将a*b[0]进行前缀和处理,用两个指针来维护前缀和,然后模拟加法过程即可
编程
void solve(){
string s1,s2;
vector<int> a,b;
cin >> s1 >> s2;
int lena=s1.size();
for(int i=s1.size()-1;i>=0;--i){
a.push_back(s1[i]-'0');//高精度乘法倒着存入
}
int d=(s2[0]-'0');
if(s1=="0" || d==0){//特判
cout << 0 << endl;
return ;
}
int t=0;
for(int i=0;i<lena || t;++i){//将a*b[0]存入到数组里
if(i<lena) t+=a[i]*d;
b.push_back(t%10);
t/=10;
}
while(b.size()>1 && b.back()==0) b.pop_back();//去除前导0
int lenb=b.size();
reverse(b.begin(),b.end());
vector<int> sum(lenb+1),ans;
for(int i=1;i<=lenb;++i) sum[i]=sum[i-1]+b[i-1];//前缀和
int len=s2.size()+lenb-1;//最大长度为b的个数加上a*b[0]的长度
int l=lenb+1,r=lenb;//双指针维护
t=0;
for(int i=len;i>=1;--i){
r=min(i,r);//r指针取小
if(l>1) l--;//l指针每次都往左移
int num=sum[r]-sum[l-1];
t+=num;
ans.push_back(t%10);
t/=10;
}
if(t) ans.push_back(t);
reverse(ans.begin(),ans.end());
for(auto i : ans) cout << i ;
cout << endl;
return ;
}