cf #802 Div.2
文章目录
A. Optimal Path
- 题意
给定一个n*m的棋盘,棋盘下标从1开始,每个格子(i,j)的值为(i-1)m+j,且只能无回头的从(1,1)到(n,m),求所经过路径的所有格子的值之和最小为多少
-
题解
贪心,无证明,当沿着第一行走到头后再沿着最后一列走到终点的路径和最小
-
代码
#include <iostream>
using namespace std;
int main() {
int T;
cin>>T;
while(T--) {
long long n,m;//注意爆int
cin>>n>>m;
cout<<m*(m+n+n*n-1)/2<<'\n';//考察等差数列的前n项和
}
return 0;
}
B. Palindromic Numbers
-
题意
给定数的长度n,以及一个长度为n的数a,求一个长度相同的数b使得a+b是一个回文数字
-
题解
假定n=4
那么对于任意一个a=9xxx,一个四位数b一定会使得a+b为5位数,所以可以指定a+b=11111,那么b可以由11111-a得到
对于任意一个a=Yxxx(Y<9),一个四位数b一定可以使得a+b=9999,所以可以指定a+b=9999,那么b可以由9999=a得到
因此,对于任意的n也是如此,但是注意n很大,所以需要高精度计算;或者转为字符串来做
-
代码
#include <iostream>
#include <vector>
using namespace std;
vector<int> sub(vector<int> A,vector<int> B)
{
vector<int> c;
int t=0;
for(int i=0;i<A.size();i++)
{
t=A[i]-t;
if(i<B.size())t-=B[i];
c.push_back((t+10)%10);
t=(t<0);
}
while(c.size()>1&&c.back()==0)c.pop_back();
return c;
}
int main() {
int t;
cin>>t;
while(t--) {
int len;cin>>len;
string s;cin>>s;
vector<int> a,b;
for(int i=s.size()-1;i>=0;i--) a.push_back(s[i]-'0');
if(s[0]!='9')
for(int i=0;i<s.size();i++) b.push_back(9);
else
for(int i=0;i<=s.size();i++) b.push_back(1);
auto c=sub(b,a);
for(int i=c.size()-1;i>=0;i--) cout<<c[i];
cout<<'\n';
}
return 0;
}
C. Helping the Nature
-
题意
对于一个数组a,经过以下三种操作使得所有值都变成0的最小操作数
1. a [ 1... i ] − 1 2. a [ i . . . n ] − 1 3. a [ 1... n ] + 1 \begin{align} &1. a[1...i]-1 \\ &2. a[i...n]-1 \\ &3. a[1...n]+1 \end{align} 1.a[1...i]−12.a[i...n]−13.a[1...n]+1 -
题解
对区间操作可以利用差分转变成对单点操作,数组a的差分数组d,操作变成
1. d [ 1 ] − 1 , d [ i + 1 ] + 1 2. d [ i ] − 1 3. d [ 1 ] + 1 \begin{align} &1.d[1]-1,d[i+1]+1\\ &2.d[i]-1\\ &3.d[1]+1 \end{align} 1.d[1]−1,d[i+1]+12.d[i]−13.d[1]+1
要使得a数组全为0,转换成求d全变为0的最小操作数。当d[i]>=0,使用操作2即可
当d[i]<0,可以用操作1把d[i]变为0;但同时也把d[1]变动了,但是没关系,1这个位置既可以用操作3加,也可以用操作2减。
那么把1位置除外,把2~n处理完,1字形单独处理
-
代码
#include <iostream>
#include <cmath>
using namespace std;
const int N=2e5+5;
long long t,n,a[N],d[N];//素以爆int
int main() {
cin>>t;
while(t--) {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) d[i]=a[i]-a[i-1];
long long res=0;
for(int i=n;i>1;i--)
if(d[i]>=0) res+=d[i];
else {
res-=d[i];
d[1]+=d[i];
}
cout<<res+abs(d[1])<<'\n';
}
return 0;
}