802 div 2的6道题,这场比较简单
A
显然先从原点走到第一行的最后一个点然后向下走最方便,我们直接计算即可
void solve()
{
ll n,m;
cin>>n>>m;
ll one=(1+m)*m/2;
ll two=(n-1)*m;
ll three=(n-1)*n*m/2;
cout<<one+two+three<<'\n';
return;
}
B
由于我们需要创造出回文数,那么如果第一位为9,我们创建多一位的回文数也就是全为1,否则我们创建全为9的回文数
void solve()
{
int n;cin>>n;
vector<int>a(n);
for(int i=0;i<n;++i)
{
char c;
cin>>c;
a[i]=c-'0';
}
vector<int>ans;
if(a[0]==9)
{
ans.assign(n+1,1);
for(int i=n;i>0;--i)
{
if(ans[i]>=a[i-1])
{
ans[i]-=a[i-1];
}
else
{
int k=i-1;
while(ans[k]==0)
{
ans[k]=9;
--k;
}
ans[k]--;
(ans[i]-=a[i-1])+=10;
}
}
}
else
{
ans.assign(n,9);
for(int i=n-1;i>=0;--i)
{
if(ans[i]>=a[i])
{
ans[i]-=a[i];
}
else
{
int k=i-1;
while(ans[k]==0)
{
ans[k]=9;
--k;
}
ans[k]--;
(ans[i]-=a[i])+=10;
}
}
}
int st=0;
while(ans[st]==0)st++;
for(int i=st;i<ans.size();++i)
{
cout<<ans[i];
}
cout<<'\n';
return;
}
C
针对范围的相同类型修改,我们一般直接考虑差分,这里也是一样,我们直接把对应的几种操作方式进行对照
1.a[1->i]-=1 -> b[1]+=1 b[i+1]+=1
2.a[i->n]-=1 -> b[i]-=1
3.a[1->n]+=1 -> b[1]+=1
最后别忘了处理b[1],注意开longlong,我这里#define int ll了已经
void solve()
{
int n;cin>>n;
vector<int>a(n+1),b(n+1);
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=n;++i)b[i]=a[i]-a[i-1];
int ans=0;
for(int i=2;i<=n;++i)
{
if(b[i]>0)
{
ans+=b[i];
}
else
{
ans+=abs(b[i]);
b[1]-=abs(b[i]);
}
}
ans+=abs(b[1]);
cout<<ans<<'\n';
return;
}
D
贪心题,首先我们考虑什么样的情况无解,那就是前i个容器的体积的和要大于i个水龙头打开的放水量,所以我们取最大的平均值,如果大于那么就无解
之后的水龙头数量很简单,就是体积和除以时间即可
void solve()
{
ll n;cin>>n;
vector<ll>a(n+1);
ll sum=0;
db average=0;
for(int i=1;i<=n;++i)
{
cin>>a[i];
sum+=a[i];
average=max(average,(double)sum*1.0/i);
}
int q;
cin>>q;
while(q--)
{
ll t;cin>>t;
if(t<average)
{
cout<<-1<<'\n';
}
else
{
cout<<(sum-1)/t+1<<'\n';
}
}
return;
}
E
首先我们考虑什么时候输出2,对于每一个需要交换的点来说,他身边最多有4个点无效,所以对于一次交换来说,我们最多改变5个点的正确性
之后我们模拟点对的交换即可,需要注意这种情况不要反复枚举,如果两个点对在一个6x6的块中
vector<vector<int>>dir={{0,0},{-1,0},{1,0},{0,-1},{0,1}};
void solve()
{
int n,m;
cin>>n>>m;
vector mp(n+1,vector<int>(m+1)),vis(mp),have(mp);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
cin>>mp[i][j];
}
}
int in_cnt=0,sx=-1,sy=-1,ans=0;
auto check=[&](int i,int j)
{
return i>=1&&i<=n&&j>=1&&j<=m;
};
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
if(mp[i][j]==1)continue;
int cnt=0;
for(int k=1;k<5;++k)
{
int ni=i+dir[k][0];
int nj=j+dir[k][1];
if(!check(ni,nj))continue;
cnt+=mp[ni][nj]<mp[i][j];
}
if(cnt==0)
{
++in_cnt;
sx=i,sy=j;
have[i][j]=1;
}
}
}
if(in_cnt==0)
{
cout<<0<<'\n';
return;
}
if(in_cnt>10)
{
cout<<2<<'\n';
return;
}
auto cal=[&](int x,int y)
{
if(mp[x][y]==1)return 0;
bool f=false;
for(int i=1;i<5;++i)
{
int nx=x+dir[i][0];
int ny=y+dir[i][1];
if(check(nx,ny)&&mp[nx][ny]<mp[x][y])
{
f=true;
break;
}
}
if(f&&have[x][y])return 1;
if(!f&&!have[x][y])return -1;//because we deal with a wrong point need to balace 1
return 0;
};
auto try_one=[&](int x,int y)
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
if(vis[i][j])continue;
int now_cnt=0;
swap(mp[i][j],mp[x][y]);
for(int k=0;k<5;++k)
{
int ni=i+dir[k][0],nj=j+dir[k][1];
if(check(ni,nj))now_cnt+=cal(ni,nj);
}
for(int k=0;k<5;++k)
{
int nx=x+dir[k][0],ny=y+dir[k][1];
if(check(nx,ny)&&abs(nx-i)+abs(ny-j)>1)now_cnt+=cal(nx,ny);
}
if(now_cnt==in_cnt)++ans;
swap(mp[i][j],mp[x][y]);
}
}
};
for(int i=0;i<5;++i)
{
int nx=sx+dir[i][0],ny=sy+dir[i][1];
if(check(nx,ny))
{
vis[nx][ny]=1;
try_one(nx,ny);
}
}
if(ans)
{
cout<<1<<' '<<ans<<'\n';
}
else
{
cout<<2<<'\n';
}
return;
}
F
还没做,贴一个别的大佬的做法(明天一定补上)