A题 题解
没什么好说的直接if:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
if (n%4) //等同于 n%4!=0
{
cout<<365<<endl;
}
else if (!(n%4)&&n%100) //等同于 (n%4==0)&&(n%100!=0)
{
cout<<366<<endl;
}
else if (!(n%100)&&n%400) //等同于 (n%100==0)&&(n%400!=0)
{
cout<<365<<endl;
}
else if (!(n%400)) //等同于 n%400==0
{
cout<<366<<endl;
}
return 0;
}
B题 题解
题意
给定一个序列,从大到小排序 ,求排序后的第二个元素在原始序列中的位置
(或从小到大排序,求倒数第二个元素原来的位置)
分析
N≤100,所有排序算法都不会超时,同时A1,A2,...,AN都不相等,所以不稳定排序也能过
由于我们需要知道排序后每个元素的位置,我们需要一个结构体,存储元素值和原来的位置
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x; //x为元素值
int th; //th为原始位置
}
a[102];
bool cmp(node a,node b)
{
return a.x>b.x;
}
int main()
{
int n;
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i].x;
a[i].th=i; //记录原始位置
}
sort(a+1,a+n+1,cmp); //从大到小排序
cout<<a[2].th<<endl; //取第二大元素的原始位置
return 0;
}
C题 题解
题意
给定序列A1,A2,...,An,给定M
设sum=∑i=1nmin(Ai,x)
求sum≤M时,x的最大值
分析
1≤N≤2×10^5
1≤Ai≤10^9
枚举算法时间复杂度为O(Nmax(Ai)),会超时
用二分查找答案的方法,时间复杂度为O(Nlogmax(Ai))
#include<bits/stdc++.h>
using namespace std;
long long a[200005];
long long n,m;
long long sum;
bool chk(long long x)
{
sum=0;
for (long long i=1;i<=n;i++)
{
sum+=min(a[i],(long long)(x));
}
return sum<=m;
}
int main()
{
cin>>n>>m;
for (long long i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
int totle=0; //计算所有交通费总和
for (int i=1;i<=n;i++)
{
totle+=a[i];
}
if (totle<=m) //如果总和<=M则输出infinite
{
cout<<"infinite"<<endl;
return 0;
}
long long l=1,r=1e9;
long long mid;
while (l<r)
{
mid=(l+r+1)>>1;
if (chk(mid))
{
l=mid;
}
else
{
r=mid-1;
}
}
cout<<l<<endl;
return 0;
}
在这里提供一个转载者的思路:
可以再度优化,可以注意到肯定是越往后越大,求出前缀和后,在check函数里再度二分(二分套二分)主体时间复杂度为O(log N log max(ai)),预处理为O(n)。但对于这道题没有必要qwq。
D题题解
题目翻译
一共n局,每一局可以赢或平,不能连续出相同,求最多赢几局
解析
考虑动态规划,定义状态f[i][j]f[i][j],表示在第ii局出jj时最多可以赢多少局(jj表示石头(1)剪刀(2)布(3))
此时考虑转移,此处以j=1为例 显然有
f[i][1]=max(f[i−1][2],f[i−1][3])+(a[i]==′S′)
同时注意在会输时f[i][j]=0
边界f[0][1]=f[0][2]=f[0][3]=0
目标max(f[n][1],f[n][2],f[n][3])
E题题解
题目翻译
求一个长度为n的序列的所有子 区间异或和,再减去长度为1的子序列异或和 (一道位贡献好题)
解析
令xor(1,i)表示前i项的异或值,xor(l,r)表示第ll项到第rr项的异或值,
那么显然有xor(l,r)=xor(1,r)⊕xor(1,l−1)。
考虑xor(l,r)的二进制第kk位是11的可能情况,当且仅当xor(1,r)和xor(1,l−1)的二进制第k位不同时才会成立。
那么我们可以固定右端点r,算出有多少个ll使xor(l,r)的第k位是1,假设已经算出右端点r的答案,现在可以O(1)推到右端点为r+1的答案,
因为对于r+1来说新增的l只有r+1一个,只需要O(1)将贡献产生即可。
最后再减去每个a[i]就是最终答案
时间复杂度O(nlogA(约为30))。