1.Codeforces Round #752 (Div. 2)
Dashboard - Codeforces Round #752 (Div. 2) - Codeforces
A.Era
题意背景:对于给定当前整数序列,要求在可以向内部添加任意数的情况下,使最终数列满足ai<=i即可,每次添加后,要求在已改变数列基础上进行改变。
自解:
遍历整个整数序列,若出现元素大于当前所处位置情况,即ai>i,那么令ai=i,当前位置向后所有元素依次减少ai-i个大小。
#include<iostream>
#include<cstring>
using namespace std;
long long a[105];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(a,0,sizeof(a));
int n;
cin>>n;
long long sum=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
if(a[i]>i)
{
sum+=(a[i]-i);
long long temp=a[i]-i;
for(int j=i;j<=n;j++)
{
a[j]-=temp;
}
}
}
cout<<sum<<endl;
}
}
官解:
无需每一项都改变,只要找到元素与对应位置差值最大即可,然后在最前面添加元素,当差值最大情况满足时,剩余所有情况全部满足。
#include<bits/stdc++.h>
using namespace std;
int main() {
int t; cin >> t;
while (t--) {
int n; cin >> n;
int ans = 0;
for (int i = 1; i <= n; i++) {
int k; cin >> k;
ans = max(ans, k - i);
}
cout << ans << '\n';
}
return 0;
}
B.XOR Specia-LIS-t
题意背景:给定一个整数序列,可以将其分割成一个或多个连续子序列,要求序列中每个元素只属于一个序列,对于每个子序列,可通过删除零个或全部的情况下生成最长递增子序列,要求每个序列对应的最长递增子序列长度按位异或等于0,判断这一可能性。
自解:
首先判断奇偶性,若为偶数,则每个元素都单独划分,最终可以得到偶数个1互相异或,最终结果一定为0。(偶数个数互相异或,无论异或任意值都为0)
若为奇数,则可判断是否存在连续两项递建或相等,此时可令其余所有元素单独划分,该两项一同划分,最终仍能得到偶数个1相互异或,最终结果同样为0,反之相反。
#include<iostream>
#include<algorithm>
using namespace std;
long long a[200005];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
int ok=1;
if(n&1)
{
long long maxn=a[0];
for(int i=1;i<n;i++)
{
if(maxn>=a[i])
{
cout<<"YES"<<endl;
ok=0;
break;
}
maxn=max(maxn,a[i]);
}
if(ok) cout<<"NO"<<endl;
}
else cout<<"YES"<<endl;
}
}
官解:
若整数序列个数为奇数且无后项小于等于前项,则为不可能情况,反之可能。
#include<bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t; cin >> t;
while (t--) {
int n; cin >> n;
vector<int> a(n + 1);
bool inc = true;
for (int i = 1; i <= n; i++) {
cin >> a[i];
inc &= a[i] > a[i - 1];
}
if (n % 2 == 0 or !inc) {
cout << "YES\n";
}
else {
cout << "NO\n";
}
}
return 0;
}
C. Di-visible Confusion
题意背景:
给定整数序列,若当前对应位置元素ai不可以被(i+1)整除,则删掉,否则保留,每一次删除要在上一次操作基础上重新计算,试判断是否可以按此方法删除整个数列。
自解:
首先我们发现,整数序列数据大小满足1≤ai≤10^9,然后我们计算一下可知,14!=87,178,291,200>ai,则对于一个数据,我们最多判断14次该数是否可以整除当前位置+1及向前推进位置+1,期间若出现成立即可,若全不可,则直接判定不可能。
#include<iostream>
using namespace std;
long long a[100005];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ok=1;
for(int i=1;i<=n;i++)
{
int yes=0;
for(int j=i+1,k=1;j>=2&&k<=14;j--,k++)
{
if(a[i]%j)
{
yes=1;
break;
}
}
ok&=yes;
if(!ok) break;
}
cout<<(ok?"YES":"NO")<<endl;
}
}
官解:与上大体相同。
D. Moderate Modular Mode
题意背景:给出两个整数x,y,试着找出一个整数n满足n mod x=y mod n,可以确定这样的n一定存在,若有多个n,可输出任意一个n即可。
自解:
考虑当x>y的情况下,即令n=x+y,此时满足x+y mod x=y=y mod x+y
若相等,即令n=x即可
对于x<y的情况,未想出正确解答方案。
官解:
对于x<y的情况,我们进行如下考虑:
1)n不可以小于x
假设n<x,则n mod x=n,y mod n<n,此时等式不成立;
2)n不可以大于y
假设n>y,则n mod x<x,y mod n=y,此时等式不成立;
由以上可知,n一定是在x~y之间的一个数,接下来我们考虑这个数具体应该是多少:
我们在一条线段上确定零点,x和y对应的位置,我们假定从零点出发,每一次走x个单位长度,则我们在走过k次后,距离y将出现小于x个的单位长度,此时我们分两步走到y,我们假定现在的出发点是p,则p=y-y mod x,同时p mod x=0,我们选取p~y中间一半距离为p1,此时p2=p+p1,会发现一点
p2 mod x=p1,而y mod p2=p1,即满足等式,n=p2,此题结束。
#include<algorithm>
using namespace std;
int main()
{
long long t;
cin>>t;
while(t--)
{
long long a,b;
cin>>a>>b;
unsigned long long ans=0;
if(a>b) ans=a+b;
else ans=b-b%a/2;
cout<<ans<<endl;
}
}
2.Codeforces Round #753 (Div. 3)
Dashboard - Codeforces Round #753 (Div. 3) - Codeforces
A. Linear Keyboard
题意背景:
给定26位小写英文字母排列顺序,接下来给出一串不规则小写英文字母字符串,计算写下当前字母耗费时间(即字母对应顺序位置)总和,写下当前字母后,下一次书写需在当前位置继续执行。
自解:
将每个字母与对应位置数字使用map相联系,计算相邻两个字母位置数字差的绝对值之和。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
map<char,int>m;
m.clear();
string s,v;
cin>>s>>v;
int x=s.size(),y=v.size();
int sum=0;
for(int i=0;i<x;i++)
{
m[s[i]]=i;
}
for(int i=1;i<y;i++)
{
sum+=abs(m[v[i]]-m[v[i-1]]);
}
cout<<sum<<endl;
}
return 0;
}
官解:
使用index函数,该函数目的返回查找对象的索引位置,若不存在则抛出异常。
例:list.index(obj)
t = int(input())
for _ in range(t):
k, s = input(), input()
res = 0
for i in range(1, len(s)):
res += abs(k.index(s[i]) - k.index(s[i - 1]))
print(res)
B.