题解 CF1151C 【Problem for Nazar】

\[\huge\mathcal{DESCRIPTION} \]

日期 2020年8月24日
编号 \(\texttt{CF1151C}\)
算法 数学差分
来源 无名小题

\[\huge\mathcal{SOLUTION} \]

设黑板上的序列为\(A_1,A_2,\ldots\)
则题目求的是:

\[\sum_{i=Left}^{Right}A_i \]

我们容易想到差分:

\[\sum_{i=Left}^{Right}A_i =\sum_{i=1}^{Right}A_i-\sum_{i=1}^{Left-1}A_i \]

这里需要用到两个公式:

  • 奇数序列的前\(k\)项和为\(k^2\)
  • 偶数序列的前\(k\)项和为\(k^2+k\)

所以我们只需要知道有多少个奇数,多少个偶数,就可以用\(\mathcal O(1)\)的时间复杂度求出和。
考虑如何求项数?
因为每次奇数和偶数都是\(2^k\)个元素拼接而成的。
所以我们可以在\(\mathcal O(logN)\)的时间内计算出两个数列的元素个数。
然后就\(AC\)\(\ldots\)

\[\huge\mathcal{CODE} \]

#include<bits/stdc++.h>
#define MOD 1000000007
using namespace std;
inline long long Sum(long long Length)
{
	register long long i;
	register long long Len1,Len2;
	Len1=Len2=0;
	register long long Log;
	Log=log2(Length+1LL);
	for(i=0;i<Log;i++)
	{
		if(!(i&1))
		{
			Len1+=(1LL<<i);
			Len1%=MOD;
		}
		else
		{
			Len2+=(1LL<<i);
			Len2%=MOD;
		}
	}
	register long long Other;
	Other=Length-(1LL<<Log)+1LL;
	Other%=MOD;
	if(!(Log&1))
	{
		Len1+=Other;
		Len1%=MOD;
	}
	else
	{
		Len2+=Other;
		Len2%=MOD;
	}
	return (Len1*Len1%MOD+Len2*(Len2+1)%MOD+MOD)%MOD;
}
int main(void)
{
	register long long Left,Right;
	cin>>Left>>Right;
	cout<<(Sum(Right)-Sum(Left-1)+MOD)%MOD<<endl;
	return 0;
}
posted @ 2020-08-24 11:51  Bushuai_Tang  阅读(159)  评论(0编辑  收藏  举报