周二天梯训练赛
A
这个题就是每次看到'.',就在它后面放一串英文字符"xixixixi."
L
其实就是看完整过了多少个视频,以及剩下的那个视频有没有播放到第m秒。
J
这个题wa了六发,好离谱,题读错了,其实就是每次都减去当前这个数字里任意一个数位,那我们就能有一个贪心思路,每次都减去最大的那个数,比如876,减去8一定比减去6更优。
点击查看代码
while(n>0){
int nn=n;
int max1=0;
while (nn > 0) {
int d = nn % 10;
nn /= 10;
max1=max(max1,d);
}
n-=max1;
ans++;
}
cout<<ans<<endl;
G
这个题也有坑,也不能算坑,就是我自己不认真读题,题目是选择三个方案中的其中一种,然后一直执行该操作,其实就是三个情况都跑一遍,看哪个最优就行。我第一遍读成了每一次操作都是三选一,也就是hard版的题意。其实就是个简单的贪心。
D
这个题还挺有意思的,我就是直接按照二维前缀和的做法套了个set,这样我就能得到每一个方框能得到的土豆情况,再把这些情况放进set里,是一个及其暴力的做法,但还好,过了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
//vector<pair<int,int>>d;
set<pair<int,int>>c[55][55];
set<set<pair<int,int>>>ss;
int a[55][55];
set<int>sx,sy;
int32_t main(){
ios::sync_with_stdio(0);
cin.tie(0) , cout.tie(0);
int n;
cin>>n;
int minx=55,miny=55,maxx=-1,maxy=-1;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
a[x][y]=1;
//d.push_back({x,y});
sx.insert(x);
sy.insert(y);
minx=min(minx,x);
miny=min(miny,y);
maxx=max(maxx,x);
maxy=max(maxy,y);
}
//cout<<minx<<" "<<maxx<<" "<<miny<<" "<<maxy<<" "<<endl;
//sort(d.begin(),d.end());
for(int i=minx;i<=maxx;i++){
for(int j=miny;j<=maxy;j++){
if(a[i][j]==1)
c[i][j].insert({i,j});
if(j>=1)
c[i][j].insert(c[i][j-1].begin(),c[i][j-1].end());
if(i>=1)
c[i][j].insert(c[i-1][j].begin(),c[i-1][j].end());
//cout<<i<<" "<<j<<" "<<c[i][j].size()<<endl;
}
}
//cout<<"--\n";
//int x=d.size();
//cout<<x<<endl;
for(auto x1:sx){
for(auto x2:sx) {
for (auto y1:sy) {
for(auto y2:sy) {
set<pair<int, int>> e;
// int x1 = min(d[i].first, d[j].first);
// int x2 = max(d[i].first, d[j].first);
// int y1 = min(d[i].second, d[j].second);
// int y2 = max(d[i].second, d[j].second);
// cout << d[i].first << " " << d[i].second << " " << d[j].first << " " << d[j].second << endl;
//e.insert({d[i].first,d[i].second});
for (auto ee: c[x2][y2]) {
if (x1 >= 1 && y1 >= 1) {
if (c[x1 - 1][y2].count(ee) || c[x2][y1 - 1].count(ee)) {
continue;
} else {
e.insert(ee);
}
} else if (x1 >= 1) {
if (c[x1 - 1][y2].count(ee)) {
continue;
} else {
e.insert(ee);
}
} else if (y1 >= 1) {
if (c[x2][y1 - 1].count(ee)) {
continue;
} else {
e.insert(ee);
}
} else {
e.insert(ee);
}
}
// for (auto eee: e) {
// cout << eee.first << " " << eee.second << " ";
// }
// cout << endl;
ss.insert(e);
}
}
}
}
cout<<ss.size()<<endl;
return 0;
}
B
这道题其实就是简单的差分前缀和问题,想要每个鸡蛋都达到所需要的温度,不就是初始温度为负的所需要的温度,执行完当前方案后看看是不是所有的鸡蛋都变成了0度以上,只要是就是合理的,然后找到最便宜的方案即可。
点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
int a[110],b[110],c[110];
struct node{
int l,r,k,p;
}d[15];
void solve(long long kk) {
int n,m;
int sum=LLONG_MAX;
int N=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
int l,r,m;
cin>>l>>r>>m;
a[l]+=(-m);
a[r+1]-=(-m);
N=max(N,r);
}
// for(int j=1;j<=N;j++){
// b[j]=b[j-1]+a[j];
// //cout<<j<<" "<<b[j]<<" ";
// }
// cout<<endl;
for(int i=1;i<=m;i++){
cin>>d[i].l>>d[i].r>>d[i].k>>d[i].p;
}
//cout<<"----\n";
for(int i=0;i<=(1<<m)-1;i++){
memset(b,sizeof(b),0);
for(int j=1;j<=N;j++){
c[j]=a[j];
}
int x=i;
int f=0;
int asum=0;
for(int j=1;j<=m;j++){
if(x%2==1){
c[d[j].r+1]-=d[j].k;
c[d[j].l]+=d[j].k;
asum+=d[j].p;
}
//cout<<x%2;
x/=2;
}
//cout<<endl;
for(int j=1;j<=N;j++){
b[j]=b[j-1]+c[j];
//cout<<b[j]<<" ";
if(b[j]<0){
f=1;
}
}
//cout<<endl;
if(f==0)
sum=min(sum,asum);
//cout<<f<<" "<<asum<<endl;
}
cout<<sum<<endl;
return ;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0) , cout.tie(0);
long long T = 1;
//cin >> T ;
for(long long i=1;i<=T;i++) solve(i);
return 0;
}
赛时只过了这几道题,赛后又补了几道题。
I
这个题其实之前做过类似的题,只是我赛时没想起来,要找到这个数有多少个因数,其实就是找质因数,然后求一下组合数,比如54可以分为3个3和1个2,因数就是4*2=8个,选不选这个质因数以及选几个质因数的问题。其实代码的重点就是预处理一下有多少个质因数以及求组合数。
点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
set<int>s;
int prime[50000];
int f[100010];
void shaishu(int n){
int ans=1;
for(int i=2;i<=n;i++){
if(f[i]==1)
continue;
else{
prime[ans++]=i;
}
for(int j=2;i*j<=n;j++){
f[i*j]=1;
}
}
}
void solve(long long kk) {
int n;
cin>>n;
int sum=1;
for(int i=1;prime[i]<=sqrt(n);i++){
if(n%prime[i]==0){
int ans=0;
while(n){
if(n%prime[i]==0){
ans++;
}
else{
break;
}
n/=prime[i];
}
sum*=(ans+1);
}
}
if(n!=1){
sum*=2;
}
cout<<sum<<endl;
return ;
}
signed main() {
// ios::sync_with_stdio(0);
// cin.tie(0) , cout.tie(0);
long long T = 1;
shaishu(100000);
cin >> T ;
for(long long i=1;i<=T;i++) solve(i);
return 0;
}
H
这个题就是G题的hard版,也就是我一开始读错题的版本,其实就是个dp,只是dp思路有点难想明白。
dp[l][r]l就是左端点,r就是右端点,当长度等于2时,其实可以理解为赋初值,它的值就是两个位置的数字和模3,当长度大于2时就可以由递推式得出,当前这个长度的值是从左边拿两个,从右边拿两个以及左右各一个三种情况得来的,找最大值即可。
最后dp[1][n]就是最后的结果。
点击查看代码
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
int l = j,r = j + i - 1;
if (r > n) continue;
if (l >= r) continue;
if (r - l + 1 == 2) dp[l][r] = (a[l] + a[r]) % 3;
else{
dp[l][r] = max({dp[l][r],(a[l] + a[l + 1]) % 3 + dp[l + 2][r],(a[r] + a[l]) % 3 + dp[l + 1][r - 1],(a[r] + a[r - 1]) % 3 + dp[l][r - 2]});
}
}
}
cout<< dp[1][n] <<endl;