AtCoder Beginner Contest 230(EF)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 230(EF)相关的知识,希望对你有一定的参考价值。

E - Fraction Floor Sum

题意:

∑ i = 1 n [ n i ] \\sum \\limits_i=1 ^n[\\fracni] i=1n[in]

思路:

整除分块板子题

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll F(ll n) 
    ll res = 0;
    for (ll l = 1, r; l <= n; l = r + 1) 
        r = n / (n / l);
        res += (r - l + 1) * (n / l);
    
    return res;

int main() 
    ll a, b;
    cin >> b;
    ll res = F(b) - F(0);
    cout << res << endl;


F - Predilection

题意:

给定长度为 N N N的数组 A A A,你可以进行任意次操作,操作为删除两个相邻的数字,并把相邻的数字相加并放到原数组的对应位置中,问进行任意次操作,会产生多少种序列?

思路:

f ( i ) f(i) f(i)定义为,到前 i i i个位置为止进行操作产生的序列数。
s u m i = ∑ j = 1 i sum_i=\\sum \\limits_j=1 ^i sumi=j=1i,假设原序列中,在合并过程中不会产生重复的序列,那么 f ( i ) = 2 ∗ f ( i − 1 ) f(i)=2*f(i-1) f(i)=2f(i1),但是在结合的过程中,可能会出现中间某一段是 0 0 0的情况,这样的话, s u m i = s u m j sum_i=sum_j sumi=sumj,这就代表着 ( j , i ] (j,i] (j,i]这段和为0,这样的话,这个 0 0 0往左结合和往右结合是一样的序列,所以会算重复情况,所以对于每个 i i i,找到左边下标最大的 j j j,且 s u m i = s u m j sum_i=sum_j sumi=sumj,这样的话,就需要让减去 f ( j ) f(j) f(j)
总结一下,就是,对于情况
j − − − − − − i − 1 j------i-1 ji1 i i i
如果 s u m j = s u m i − 1 sum_j=sum_i-1 sumj=sumi1的话,就是 f ( i ) 减 去 f ( j ) f(i)减去f(j) f(i)f(j)

#include <iostream>
#include <map>

using namespace std;

typedef long long ll;

const int mod = 998244353;
ll dp[200007];
ll sum[200007];
map<ll, int> mp;

int main() 
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) 
        int a;
        cin >> a;
        sum[i] = sum[i - 1] + a;
    

    ll temp = 1;
    for (int i = 1; i <= n; i++) 
        
        dp[i] = temp % mod;
        (temp *= 2) %= mod;
        (temp += mod - mp[sum[i]]) %= mod;
        mp[sum[i]] = dp[i];
        
    
    cout << dp[n] << endl;
    return 0;

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于AtCoder Beginner Contest 230(EF)的主要内容,如果未能解决你的问题,请参考以下文章