C题 求和
给定 n 个整数 a1, a2, · · · , an ,求它们两两相乘再相加的和,即 S = a1 · a2 + a1 · a3 + · · · + a1 · an + a2 · a3 + · · · + an-2 · an-1 + an-2 · an + an-1 · an.
解法
前缀和秒了
D题 P8773 [蓝桥杯 2022 省 A] 选数异或选数异或
给定一个长度为 n 的数列 A1, A2, · · · , An 和一个非负整数 x,给定 m 次查询, 每次询问能否从某个区间 [l,r] 中选择两个数使得他们的异或等于 x 。
思路
首先 a^b=x <=> a=b^x
对于数组a中任意数ai,其对应唯一的另一数x^ai。也就是说,每个a[i]都只有唯一一个可行解。
那么,可以使用数组f[r] 记录区间[1,r]中所有合法组合的最大左端点的下标,注意 f[r]对应的右端点可以不是r
那么对每次询问[l,r] 只要判断区间 [f[r],r] 是否在 [l,r] 中即可,也就是l和f[r]比较。
对于数组f[],显然f[i]=max(f[i-1],xxx)。问题转化为如何求xxx。
从左往右遍历数组a,如果a[i]^x,在[1,i]中出现过(设为j),f[i]=max( f[i-1],j )
用一个map储存 a[i] 和 i 的对应关系,即 map[a[i]]=i
f[i]=max(f[i-1],mp[x^a[i]]);
#include<iostream>
#include<map>
#include<vector>
using namespace std;
#define imp map<int,int>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
int main(){
int n,m,x;
cin>>n>>m>>x;
vector<int> a(n+1),f(n+1);
imp mp;
FOR(i,1,n){
cin>>a[i];
f[i]=max(f[i-1],mp[x^a[i]]);
mp[a[i]]=i;
}
int l,r;
FOR(i,1,m){
cin>>l>>r;
if(l<=f[r])cout<<"yes\n";
else cout<<"no\n";
}
}
E题 P8774 [蓝桥杯 2022 省 A] 爬树的甲壳虫
有一只甲壳虫想要爬上一颗高度为 n 的树,它一开始位于树根, 高度为 0,当它尝试从高度 i−1 爬到高度为 i 的位置时有 Pi 的概率会掉回树根, 求它从树根爬到树顶时, 经过的时间的期望值是多少。
数学题
思路
设 f[i]为 i 到 n 花费的时间,p[i]为从i到i+1掉下去的概率,显然f[n]=0。
f[i] = p[i+1]*f[0]+ (1+ (1-p[i+1])*f[i+1] )
分别带入直到只有f[0]和f[n]得到
f[0]=∏(1−p[i])f[n]+f[0]∑p[i]∏(1−pj)+∑∏(1−pj)
因为f[n]=0,f[0]= ∑∏(1−pj) / (1-∑p[i]∏(1−pj))
不会写逆元,寄