• CF1485F Copy or Prefix Sum 题解


    Problem

    传送门:CF1485F Copy or Prefix Sum
    给出一个长度为 (n) 的序列 (b_1,b_2,dots ,b_n) ,求出有多少种序列(a_1,a_2,dots,a_n) 满足:

    (forall i in [1,n],b_i = a_i or b_i = sum_limits{j=1}^i a_j).

    Sol

    考虑当前我们填到第 (i) 位,所填的数的和是 (S) , 那么,我们可以填:

    1.(b_i)

    2.(b_i-S)

    于是,我们可以记(dp_i) 代表当前填的数之和为 (i) 的方案数,于是,两种操作对应这:

    1.(dp_{i+b_i} = dp_i)

    2.(dp_{b_i} = sum_limits{j=-inf}^inf{dp_j})

    但是要注意,当 (b_i = b_i - S) 也就是 (S = 0) 时,是只能算一遍的,减去 (dp_0) 即可。

    然后维护一个 (map) ,代表 (DP) 数组,维护一个 (totadd) ,代表全局移位(因为有操作一),再维护一个目前的 (ans),就搞完了。

    Code

    #define in read()
    int read(){int x = 0,sgn = 1;char ch = getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')sgn=-1;for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);return x*sgn;}
    
    const int N = 2e5+10;
    const int mod = 1e9+7;
    
    int n,b[N];
    
    void solve(){
    	n = in;for(int i = 1;i <= n;i++) b[i] = in;
    	map<ll,ll> f; f.clear();
    	f[0] = 1; ll totadd = 0,ans = 1;
    	for(int i = 1;i <= n;i++){
    		ll tmp; tmp = (ans - f[-totadd] + mod)% mod; ans = (ans + tmp) % mod; (f[-totadd] += tmp) %= mod;
    		totadd += b[i];
    	}ans = (ans + mod) %mod;
    	printf("%lld
    ",ans);
    }
    
    int main(){
    	int test = in;
    	while(test--) solve();
    	return 0;
    }
    

    彩蛋

    1.出题人说 "F is easier than C."确实。

    1. 于是我打完 C 后开始搞 F
    2. 搞完了 F,确实是正解,但是已经 0 :53 了,比赛已经结束了 3 分钟
    3. 其实 F 早就搞完了,有两个神奇的错误调了一会儿,Can you guess ?
    本博客作者:Werner_Yin(https://www.cnblogs.com/werner-yin/) ,转载时请注明出处,谢谢支持!
  • 相关阅读:
    背景(北极狐)
    【面试】java基础
    C#分享海报生成
    jetson nano 4gb记录
    jetson nano 2gb相关问题
    分布式系列-分布式ID
    Mybatis-Plus 多租户模式忽略某个方法
    IDEA 集成 Docker 插件实现一键远程部署 SpringBoot 应用,无需三方依赖,开源微服务全栈有来商城线上部署方式
    《将博客搬至CSDN》
    elk收集docker容器的json格式日志
  • 原文地址:https://www.cnblogs.com/werner-yin/p/solution-CF-1485-F.html
Copyright © 2020-2023  润新知