HDOJ2018多校第一场补题1007 Chiaki Sequence Revisted

本文解析了一道复杂的数列求和问题,通过观察数列规律发现每个项在数列中出现的次数与其因子2的数量有关。利用此规律,文章介绍了如何通过二分查找确定关键位置,并最终高效地计算出数列的前缀和。

emmmmmm

事先声明下,这题不是我补的,毕竟对于数学八字不合,是我队友补的,然后,由于B站优良的学习氛围,他选择了在B站上发,我就当个板砖工了~

B站链接:https://www.bilibili.com/read/cv795958

 

题意是,给了一个数列的递推公式,让我们求前缀和Sn,一共有T组case,Sn可能很大,答案对10^9+7取余数,n为 <= 10^18的正整数。T <= 10^5

 

拿到这题咱也很蒙圈(当然考试的时候没做出来啦)。找规律的题目真的很吃智商……

 

根据赛后的大佬吹水直播给的提示,对于该数列中的一个项An,这一项的数字在数列中将会出现的次数是lowbit(An)的二进制位数,即An中含有因子2的个数再+1。

lowbit(x)=x&(-x);

这样数列中出现1次的数会是1,3,5,7,……

出现2次的数将会是2,6,10,14…… (即1,3,5,7……每项×2^1)

出现3次的数将会是4,12,20,28…… (即1,3,5,7……每项×2^2)

……以此类推……

N An

1   1

2   1

3   2

4   2

5   3

6   4

7   4

8   4

9   5

10 6

11 6

12 7

13 8

14 8

15 8

16 8

17 9

18 10

19 10

20 11

21 12

22 12

23 12

24 13

25 14

但是考虑到我们可能不会取到完整的数列,可能对于某一项的数字y,在截取的数列中出现的次数小于lowbit(y)的二进制位数,又观察可知数列是单调不下降的,所以少出现的项一定和最后出现的数字相同,只需要把这一种数字缺失的次数补回来就行了。

接下来的问题就是,怎么找到这样的位置,使得在该位置之前(包括它自身这个位置在内)所有的数字都出现了我们预计出现的次数。

记X为这个位置上的数字。

出现1次的数会是1,3,5,7,…… 这些数字对应1~X中奇数的个数

出现2次的数将会是2,6,10,14…… 这些数字对应1~[X÷2]中奇数的个数

出现3次的数将会是4,12,20,28…… 这些数字对应1~[X÷4]中奇数的个数

……以此类推……

那么最后一次出现数字X对应的项的下标为

n0=[(X+1)/2]*1+[([X/2]+1)/2]*2+[([X/4]+1)/2]*3+[([X/8]+1)/2]*4+[([X/16]+1)/2]*5+……

[]为下取整

观察到当X为2的幂的时候,对应的下标为2X,

所以可以大胆估计这个X会在n÷2附近取到。

数据可能取到10^18,这当然要用二分搜索,但是裸的二分依然会超时。根据大佬的提示,把X的二分区域缩小到(n÷2)±100就可以了。

最后要统计前缀和Sn,我们这样计算:

记前面完整取到的项到下标n0为止,n0在上面已经给出表达式。

记出现i次的数的个数为Xi,容易得到Xi为[([X/(2^(i-1))]+1)/2]

[]为下取整

出现1次的数会是1,3,5,7,…… 这部分和为 1*(2^0)*(X1)^2

出现2次的数将会是2,6,10,14…… 这部分和为 2*(2^1)*(X2)^2

出现3次的数将会是4,12,20,28…… 这部分和为 3*(2^2)*(X3)^2

……以此类推……

然后是把不足的部分加上去,这部分为 (n-n0)*(X+1)

注意可能中间步骤超过long long范围,要及时取模。

最后,附上队友优美的代码

#include<bits/stdc++.h>
using namespace std;
const long long M=1000000007;
long long lowbit_length(long long x)
{
    long long ret=1;
    while(!x&1)
    {
        ret++;
        x>>=1;
    }
    return ret;
}
long long findnum(long long x)
{
    long long ret=1,i=1;
    while(x)
    {
        ret+=(i*(long long)((x+1)>>1));
        x>>=1;i++;
    }
    return ret;
}
long long mul(long long a,long long b,long long c)
{
    a%=M;b%=M;c%=M;
    return (((a*b)%M)*c)%M;
}
long long findx(long long n)
{
    long long left=(n>>1)-100,right=(n>>1)+101,mid;
    if(left<=0)left=1;
    while(left<right)
    {
        mid=(left+right+1)>>1;
        if(findnum(mid)>n)right=mid-1;
        else left=mid;
    }
    return left;
}
int main()
{
    long long T,n,x,n0,x0,ans,tmp,tmp2;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        if(n==1){cout<<"1\n";continue;}
        x=findx(n);
        n0=findnum(x);
        x0=x;
        ans=(1+mul(n-n0,x+1,1))%M;
        tmp2=1;
        for(int i=1;x0>0;i++)
        {
            tmp=(x0+1)>>1;
            tmp=mul(tmp,tmp,1);
            ans=(ans+mul(tmp,i,tmp2))%M;
            tmp2=(tmp2<<1)%M;
            x0>>=1;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

 

内容概要:本文介绍了一项创新性未发表的研究,即利用元宇宙优化算法(Multiverse Optimizer, MVO)对分时电价下的需求响应与综合能源系统调度问题进行建模与求解,旨在实现能源系统的经济性、高效性与可持续性运行。该研究构建了包含种能源设备(如光伏、风机、燃气轮机、储能系统等)及可调节负荷的综合能源系统模型,充分考虑了用户侧的需求响应行为在分时电价机制下的响应特性,通过MVO算法对系统运行成本、能源利用率、碳排放等目标进行协同优化,实现了日前调度计划的智能决策。研究还提供了完整的MATLAB代码实现,便于研究人员复现实验、验证算法性能,并为进一步研究提供可靠的仿真基础。; 适合人群:具备一定电力系统、优化算法及MATLAB编程基础的科研人员、研究生以及从事能源互联网、综合能源系统规划与运行的技术工程师。; 使用场景及目标:① 学习并掌握元宇宙优化算法在复杂能源系统调度中的具体应用方法;② 研究分时电价机制如何通过需求响应引导用户参与电网互动,实现削峰填谷;③ 实现综合能源系统(IES)中冷、热、电、气等种能源的协同优化调度,以降低运行成本、提高新能源消纳能力和系统可靠性;④ 为相关领域的学术研究提供可复现的代码实例和仿真平台。; 阅读建议:此资源以MATLAB代码为核心载体,深入剖析了算法应用与系统建模的全过程。建议读者在学习时,不仅应关注代码的实现细节,更要理解其背后的数学模型、优化目标设定和约束条件的物理意义。建议结合文档中的模型描述,逐步调试代码,观察不同参数和场景下的优化结果,从而深刻掌握综合能源系统优化调度的设计思想与关键技术。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值