首页 > 其他分享 >[题解]P2671 [NOIP2015 普及组] 求和

[题解]P2671 [NOIP2015 普及组] 求和

时间:2024-10-22 20:32:13浏览次数:1  
标签:P2671 NOIP2015 int 题解 sum times col define

P2671 [NOIP2015 普及组] 求和

可以发现我们对相同颜色且编号奇偶性相同的元素归为一组,组内的元素两两都满足题目条件,且这样可以不重不漏覆盖所有答案。

设分完组之后,某一组内的元素编号分别是\(a_1,a_2,\dots,a_q\),数字分别是\(b_1,b_2,\dots,b_q\),则根据题意,该组的答案是:

\[\large{\sum\limits_{1\le j<i\le n}(a_i+a_j)\times(b_i+b_j)} \]

对于每个\(i\),答案是:

\[\large{\sum\limits_{j=1}^{i-1}b_i\times c_i+b_i\times c_j+b_j\times c_i+b_j\times c_j} \]

所以维护\(b\)、\(c\)、\(b\times c\)三个前缀和数组即可。这样对于每个\(i\)都可以\(O(1)\)求出。总时间复杂度\(O(n)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define mod 10007
#define N 100010
#define M 100010
using namespace std;
int n,m,col[N],a[N],nn[2*M],ans;
vector<int> b[2*M],c[2*M],preb[2*M],prec[2*M],pre[2*M];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>col[i];
	for(int i=1;i<=(m<<1);i++) b[i].emplace_back(0),c[i].emplace_back(0);
	for(int i=1,pos;i<=n;i++)
		pos=col[i]+(1-i%2)*m,
		b[pos].emplace_back(a[i]),
		c[pos].emplace_back(i),
		nn[pos]++;
	for(int i=1;i<=(m<<1);i++){
		pre[i].resize(nn[i]+1);
		preb[i].resize(nn[i]+1);
		prec[i].resize(nn[i]+1);
		for(int j=1;j<=nn[i];j++){
			preb[i][j]=(preb[i][j-1]+b[i][j])%mod;
			prec[i][j]=(prec[i][j-1]+c[i][j])%mod;
			pre[i][j]=(pre[i][j-1]+b[i][j]*c[i][j]%mod)%mod;
		}
		for(int j=2;j<=nn[i];j++){
			ans=(ans+b[i][j]*c[i][j]%mod*(j-1)%mod)%mod;
			ans=(ans+pre[i][j-1])%mod;
			ans=(ans+b[i][j]*prec[i][j-1]%mod)%mod;
			ans=(ans+c[i][j]*preb[i][j-1]%mod)%mod;
		}
	}
	cout<<ans<<"\n";
	return 0;
}

代码稍稍有些繁琐了,其实前缀和什么的,都可以分组的同时记录,由于只需要用到上一个位置的前缀和,所以第二位可以去掉。可以参考此题解的代码。


题解里也有用纯数学推导的,这里也写一下:

依旧设当前组的元素编号分别是\(a_1,a_2,\dots,a_q\),数字分别是\(b_1,b_2,\dots,b_q\)。这样该组的答案是:

\[\begin{aligned} &\sum\limits_{1\le j<i\le n}(a_i+a_j)\times(b_i+b_j)\\ =\ &(a_1+a_2)\times(b_1+b_2)+(a_1+a_3)\times(b_1+b_3)+\dots+(a_2+a_3)\times(b_2+b_3)+\dots+(a_{q-1}+a_q)\times(b_{q-1}+b_q)\\ =\ &a_1\times(b_1+b_2+b_1+b_3+\dots+b_1+b_q)+a_2\times(b_2+b_1+b_2+b_3+\dots+b_2+b_q)+\dots+a_q\times(b_q+b_1+b_q+b_2+\dots+b_q+b_{q-1})\\ =\ &a_1\times((q-2)\times b_1+\sum\limits_{i=1}^{q}b_i)+a_2\times((q-2)\times b_2+\sum\limits_{i=1}^{q}b_i)+\dots+a_q\times((q-2)\times b_q+\sum\limits_{i=1}^{q}b_i) \end{aligned}\]

于是我们维护每一组的\(\sum\limits_{i=1}^{q}b_i\),一次遍历统计答案即可。

点击查看代码
#include<bits/stdc++.h>
#define N 100010
#define M 100010
#define mod 10007
#define int long long
using namespace std;
int n,m,a[N],col[N],q[M][2],sum[M][2],ans;
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		cin>>col[i];
		q[col[i]][i&1]++;
		sum[col[i]][i&1]=(sum[col[i]][i&1]+a[i])%mod;
	}
	for(int i=1;i<=n;i++){
		ans=(ans+i%mod*(a[i]*(q[col[i]][i&1]-2)%mod+mod+sum[col[i]][i&1])%mod)%mod;
	}
	cout<<ans<<"\n";
	return 0;
}

标签:P2671,NOIP2015,int,题解,sum,times,col,define
From: https://www.cnblogs.com/Sinktank/p/18493560

相关文章

  • 20241021 校测T1 致敬传奇捆绑测试题目(Perm) 题解
    题解:致敬传奇捆绑测试题目Perm来自不知道什么时候的回忆。给定正整数\(n\),一个\(1\simn\)的排列\(p\)是一个好排列,当且仅当使得对于任意\(1\lek<n\),都有\(\sum_{i=1}^kp_i>p_{k+1}\)。现在请你求出字典序第小的好排列\(p\)。\(1\len\le10^6\),\(1\lek\le......
  • [ARC133E] Cyclic Medians 题解
    一点不会套路。思路对于中位数相关,发现我们不好直接表示与中位数有关的内容。不妨枚举\(x\),把大于\(x\)的标为\(1\),小于等于\(x\)的标为\(0\),这样把所有最终为一的方案数加起来就是原来的答案。大概是这样一个东西:\[k=\sum_{i=0}^k[i<k]\]这个怎么求呢。发现若一组......
  • Public NOIP Round #7 T3 黑白棋子 题解
    Description有一棵\(n\)个点的树,顶点的编号为\(1\)到\(n\)。对于树中的每个顶点,可能存在一个白色的棋子、一个黑色的棋子,或者没有棋子。树上正好有\(w\)个白色棋子和\(b\)个黑色棋子。另外,对于每一对具有相同颜色棋子的顶点,存在一条路径,路径上的每个顶点都包含相同颜色......
  • AT_agc064_c [AGC064C] Erase and Divide Game 题解
    先考虑所有\(l_i=r_i\)时怎么做,可以建出反向Trie树,问题转化为从根开始每次向左子树或右子树走,第一个拿到空子树的人输,直接在Trie上dp即可。考虑从叶子层开始对每一层的点合并两个子树的dp值,发现每一层值相同的连续段是较少的。于是可以维护这些连续段,每次合并要将每个......
  • 洛谷P2596 [ZJOI2006] 书架 题解 splay tree 模板题
    题目链接:https://www.luogu.com.cn/problem/P2596主要涉及的操作就是:找到某一个编号的点(这个操作可以不用splaytree维护)删除某个点将某一个点插入到最前面,最后面,或者某一个位置查询前序遍历为\(k\)的节点编号因为每次删除都会又把这个点加回去,所以可以复用\(n\)个......
  • [题解]CF825E Minimal Labels
    LPhang为什么是神?思路显然可以想到一个错误的贪心:直接拓扑排序,每一次选择当前可以拓展的点中最小的元素进行编号。由于可能存在一个值较小的元素被藏在一个较大的元素后面,这种贪心就会出问题。出问题的本质原因就是我们希望字典序最小,就得使得越小的位置分配到更小的值。不妨......
  • 历年CSP-J初赛真题解析 | 2017年CSP-J初赛完善程序(27-36)
    学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。附上汇总贴:历年CSP-J初赛真题解析|汇总_热爱编程的通信人的博客-CSDN博客(快速幂)请完善下面的程序,该程序使用分治法求x......
  • CF2023D Many Games 题解
    赛时被创四了。思路考虑我们什么时候合并会比原来优。例如,我们现在要合并\(p_1,w_1\)和\(p_2,w_2\),同时保证,\(w_1\gew_2\)。那么有:\[\frac{p_1}{100}\timesw_1\le\frac{p_1}{100}\times\frac{p_2}{100}\times(w_1+w_2)\]\[\frac{p_2}{100}\timesw_2\le\frac{p_1}{......
  • 01 Eclipse使用Maven慢的问题解决
    1.Eclipse使用的是内置的MavenEclipse有可能使用了内置的Maven,而不是独立安装的Maven。如果使用Eclipse内置的Maven,默认的settings.xml可能并未生成。你可以按以下步骤检查或修改Maven设置路径:a.检查Eclipse使用的Maven配置点击Window->Preferences在......
  • 【题解】Solution Set - NOIP2024集训Day58 字符串
    【题解】SolutionSet-NOIP2024集训Day58字符串https://www.becoder.com.cn/contest/5658「CF1466G」SongoftheSirens考虑对于\(s_i\),算钦定必须覆盖到\(t_i\)的匹配个数\(f_i\)。注意到\(s\)每次长度都会\(\times~2\)左右,其长度在\(O(\log|w|)\)的时候就......