A-等差数列
将三个数从小到大排序再判断。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int A[3];
cin >> A[0];
cin >> A[1];
cin >> A[2];
sort(A, A + 3);
if (A[2] - A[1] == A[1] - A[0])
cout << "Yes";
else
cout << "No";
return 0;
}
B-次高山峰
简单模拟,找次大值即可。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
int n,t,t1,t2;
string s,s1,s2;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin>>n;
while(n--){
cin>>s>>t;
if(t>t1){
s2=s1;t2=t1;
s1=s;t1=t;
}
else if(t<t1&&t>t2){
s2=s;t2=t;
}
}
cout<<s2<<endl;
return 0;
}
C-简单计数问题
问题关键在于对于数组A中的数,快速找到有多少个满足。可以记录一个数组,输入C数组中的数x时,,代表对于,可以找到个使其相等。那么答案就是的和。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e5+10;
int a[N],b[N],cnt[N],ans;
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++){
int x;
cin>>x;
cnt[b[x]]++;
}
for(int i=1;i<=n;i++){
ans+=cnt[a[i]];
}
cout<<ans<<endl;
return 0;
}
D-简单字符串
从第一位开始枚举每一位,由于有a个a和b个b,那么第一位时a的有个数,在枚举的同时,a的值与b的值同样在变化,同理第二位为a的有。通过判断值的大小来确定当前位为a或b。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=110;
ll C[N][N];
void get_C(int n) {
C[0][0] = 1;
for(int i = 1; i <= n; i++) {
C[i][0] = 1;
for(int j = 1; j <= i; j++)
C[i][j]= C[i - 1][j] + C[i - 1][j - 1];
}
}
int main(){
int a,b;
ll k;
cin>>a>>b>>k;
get_C(60);
int n=a+b;
for(int i=1; i<=n; i++) {
ll now = C[n-i][a - 1];
if(a==0)now=0;
if(k > now) k -= now, putchar('b'), --b;
else putchar('a'), --a;
}
return 0;
}
E-简单异或问题
考虑异或的性质,a xor b = a xor c xor b xor c。
那么记为路径的异或。答案为。我们按位来讨论贡献。
记分别为二进制下0/1的个数。那么第j位的贡献位,将每一位求和即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+5,mod=1e9+7;
int n,head[N],cnt;
struct node{
int next,to,w;
}e[N<<1];
void add(int from,int to,int w){
e[++cnt]=(node){head[from],to,w};
head[from]=cnt;
}
int f[N],num0[70],num1[70];
void dfs(int x,int fa){
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(y==fa)continue;
f[y]=f[x]^e[i].w;
dfs(y,x);
}
}
signed main(){
n=read();
for(int i=1;i<n;++i){
int u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
dfs(1,0);
for(int i=1;i<=n;++i){
for(int j=0;j<60;++j){
if(f[i]&(1ll<<j))num1[j]++;
else num0[j]++;
}
}
int ans=0;
for(int i=0;i<60;++i){
int tmp=num0[i]*num1[i]%mod;
ans=(ans+(1ll<<i)%mod*tmp%mod)%mod;
}
print(ans);
return 0;
}
F-新版移球游戏
很明显能看出是个dp问题。对于每一个球,有四种状态,去任意一个位置,最左边,最右边,不移动。对于不移动的球,它很有特殊性。可以围绕不动的球来设计状态。如果记不动的球为,表示不进行操作。
那么对于 最小代价
对于代价为
对于代价为。
记为将已经排好,且i位置不使用操作的最小代价,为编号为i的初始在的位置。i需要从它左边的j转移过来。考虑从转移到,那么
最终答案为。
为了方便转移,计算时记录的前缀最小值额外加上了
转移时可用树状数组维护前缀最小值。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+5;
int n,pos[N],a[N],b[N],c[N];
int suma[N],pre[N],suf[N],f[N],bit[N];
void add(int x,int y){
for(int i=x;i<=n;i+=(i&-i)){
bit[i]=min(bit[i],y);
}
}
int query(int x){
int ans=1e18;
for(int i=x;i>=1;i-=(i&-i)){
ans=min(ans,bit[i]);
}
return ans;
}
signed main(){
cin>>n;
for(int i=1;i<=n;++i){
int x;
cin>>x;
pos[x]=i,bit[i]=1e18;
}
for(int i=1;i<=n;++i){
cin>>a[i]>>b[i]>>c[i];
suma[i]=suma[i-1]+a[i];
pre[i]=pre[i-1]+min(a[i],b[i]);
}
for(int i=n;i>=1;--i)suf[i]=suf[i+1]+min(a[i],c[i]);
int ans=1e18;
for(int i=1;i<=n;++i){
f[i]=min(pre[i-1],query(pos[i])-(suma[n]-suma[i-1]));
ans=min(ans,f[i]+suf[i+1]);
add(pos[i],f[i]+suma[n]-suma[i]);
}
cout<<ans<<endl;
return 0;
}