很好的数学专题,让我发疯
A.
居然直接加了个限制,要求是对于连续的子序列,要求相等,关键是一定有解,用到了鸽笼原理
假设对两个数列求前缀和之后,分别是An,Bn
最终要得到 Ai - Aj = Bk - Bl
但是这样肯定是很麻烦的,要枚举,但是如果移项就可以得到一个有相同格式的式子
Ai - Bk = Aj - Bl
下标从0开始,对于Aj - Bi中的i,找到一个最小的 j 让差值为非负,那这个差值的范围一定是 [0,n),又下标是从 0 到 n,所以最多 n 种可能的结果,但实际有 n + 1种结果,说明一定有两对下标满足,那么这样就找到最终答案了。
查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 10;
typedef long long LL;
int n;
LL a[MAXN], b[MAXN];
pair<int, int> vis[MAXN];
void print(int m, int l, int r)
{
cout<< l - vis[m].first << '\n';
for(int i = vis[m].first + 1;i <= l;i++) cout << i << " \n"[i==l];
cout<< r - vis[m].second << '\n';
for(int i = vis[m].second + 1;i <= r;i++) cout << i << " \n"[i==r];
return ;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for(int i = 1;i <= n;i++) cin>> a[i], a[i] += a[i-1];
for(int i = 1;i <= n;i++) cin>> b[i], b[i] += b[i-1], vis[i].first = vis[i].second = -1;
vis[0].first = -1;
int poi = 0;
for(int i = 0;i <= n;i++)
{
while(b[poi] < a[i]) poi++;
int m = b[poi] - a[i];
if(vis[m].first != -1)
{
print(m, i, poi);
return 0;
}
vis[m] = {i, poi};
}
}
B
关键词:组合数学,秦九韶
C
关键词:高斯消元 组合数学 逆矩阵
一开始以为是通过数学公式,求极限来算,结果是求每个点经过次数的期望,从点的经过期望来求边的经过期望。
相连的两点间期望相互制约,通过这个建立n个n-1元的一次方程,通过高斯消元求解即可。
最后把边的期望排序就能算出结果。
L
怎么说呢,虽然猜到了最终肯定是把点的权排序,按个取,但是没想到怎么处理边权
一直在想怎么在点和边上怎么取舍,但实际上,对于两点一边,总共就两种情况。
一种情况是,双方各染色一个点
另一种情况就是,一方染了两个点,得到了边权
那这样最终的结果,要么就是一方得到整条边的权,要么就是双方都得不到
由于最终求得是得分的差值,那么就不关注究竟是谁得到了这条边,只要最终得到的差值对就行了。
如果将边权一分为二,分别加到两个端点上,无疑是符合最终结果的。
这个题和上一次训练的期望比较类似,既然问号有可能是o也可能是x,那连击的长度就有两种可能,一种是原长l,一种是l+1,一半一半的概率,就是l+0.5了
标签:2024.1,26,期望,int,大寄特,最终,vis,MAXN,差值 From: https://www.cnblogs.com/xxx3/p/17990933