A. Optimal Path
Problem - A - Codeforceshttps://codeforces.com/contest/1700/problem/A题意,按照从左往右,从上到下的顺序去给一个n*m的表格从1开始赋值,求一条路,令它的权值(路上所有格子的值相加)最小.
思路:签到,先从第一个格子往右走到边界,再往下走到结果即可.
#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
int n,m;
cin>>n>>m;
int ans=0;
ans+=(1+m)*m/2;
ans+=(m+m+(n-1)*m)*n/2;
ans-=m;
cout<<ans<<"\n";
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
B. Palindromic Numbers
Problem - B - Codeforceshttps://codeforces.com/contest/1700/problem/B
题意:给你一个n,还有一个数,让这个数加上这个n为位数的数(无前导0),成为一个回文.
思路:贪心,模拟,减少操作.当所给的数第一位不是9时,就取一个长度为n,每一位为9的数去减去所给的数,即为结果.如果第一位是9,那我们可以去一个位数为n+1的每一位为1的数,去减去所给的数,即可.这里减法要用高精度.
#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
char s[100005];
vector<int>sub(vector<int>&a,vector<int> &b)
{
vector<int> c;
for(int i = 0,t = 0; i < a.size(); i++){
t = a[i] - t;
if (i < b.size()) t -= b[i];
c.push_back((t+10)%10);
if (t < 0) t = 1;
else t = 0;
}
while(c.size()>1&&c.back()==0) c.pop_back();
return c;
}
void solve()
{
int n;
cin>>n>>s+1;
if (s[1] != '9')
{
for(int i=1;i<=n;i++)
cout<<9-(s[i]-'0');
cout<<'\n';
}
else
{
vector<int>a,b;
for(int i=1;i<=n+1;i++)
a.push_back(1);
for(int i=n;i;i--)
b.push_back(s[i]-'0');
auto c=sub(a,b);
for(int i=c.size()-1;i>=0;i--)
cout<<c[i];
cout<<'\n';
}
return ;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
C. Helping the Nature
Problem - C - Codeforceshttps://codeforces.com/contest/1700/problem/C题意:给你一个数组,你可以选择1-i的元素将他们-1,也可以选择i-n的元素将他们-1,也可以将所有的都+1,问多少次之后可以把所有元素置为0.
思路:看见区间操作,而且是c题,就想到从前缀和,差分入手.果不其然,当转换为差分是,这三个操作就改变了.第一个操作就变成了了sub[1]-1,sub[i+1]+1,第二个操作就是sub[i]-1,第三个就是sub[1]+1.那么就可以直接对着差分数组求值.当当前元素<0时,就采用第一个操作将其置为0.当>0时采用第二个操作.最后用第二个和第三个操作来处理sub[1]即可.
#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
int arr[200005];
int sub[200005];
void solve()
{
int ans=0,n;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&arr[i]);
sub[i]=arr[i]-arr[i-1];
}
for(int i=2;i<=n;i++)
{
if(sub[i]<0)
{
sub[1]-=abs(sub[i]);
ans+=abs(sub[i]);;
}
else
ans+=sub[i];
}
ans+=abs(sub[1]);
printf("%lld\n",ans);
return ;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
D. River Locks
Problem - D - Codeforcesqqhttps://codeforces.com/contest/1700/problem/D题意:有n个水库,每个水库上面都可以有一个龙头防水,连续的水库也可以连着放水,每秒1升水.n赐询问,每次问在t秒把所有水库装满要开几个水龙头.
思路:很妙的思维题.一开始就想到,直接拿总的水量除以时间,向上取整,就会得到需要几个水龙头把它装满.但是,要考虑一些情况,就是前几个水库必须要都花时间装满之后,才会流到下一个水库,就是说我们要考虑的是用前面所有水库都装满的时间去除以所给的时间,才能知道需要几个水龙头.所以我们要用每一个水库的前缀和去除以当前便利了的水库的个数,向上取整,这个数就是把当前遍历过的前几个水库装满所需要的的时间.为了保证装满所有水库,要去这个时间的max,如果小于这个max,就说明我可能到某个水库时还没有装满,水不会往下流.这个就是-1的情况,其余的用总水量除以时间向下取整即可.
#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
int x,sum[200005];
void solve()
{
int n,q,maxx=-1;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
sum[i]=sum[i-1]+x;
maxx=max(maxx,(sum[i]-1)/i+1);
}
scanf("%lld",&q);
while(q--)
{
int y;
scanf("%lld",&y);
if(y<maxx)
printf("-1\n");
else
printf("%lld\n",(sum[n]-1)/y+1);
}
return;
}
signed main()
{
solve();
return 0;
}
加油!
|