Codeforces Round #740 (Div. 2) D1. Up the Strip (simplified version)

Posted yueshehanjiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #740 (Div. 2) D1. Up the Strip (simplified version)相关的知识,希望对你有一定的参考价值。

D1. Up the Strip (simplified version)

题意

你现在在n

你可以n - x [ 1 <= x <= n - 1 ]
你也可以 n / x [ 2 <= x <= n ]

问你从n到1的方案数对m取模
2 ≤ n ≤ 2e5  1e8 < m < 1e9

思路

首先
大致方向先确定
是动态规划
然后先把暴力的n^2的代码写出来
写出来之后在考虑优化

假设f[i]
表示从第i层到第1层的方案数
转移方程题目已经给你了

先看下面暴力的代码
#include<bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define re register int
#define pll pair<int,int> 
#define pb push_back
#define x first 
#define y second 
#define sf(x) scanf("%d",&x)
#define sfl(x) scanf("%lld",&x)
#define de(x) cout << x << "\\n" ;
typedef long long ll ;
using namespace std;
const int N = 1e6 + 10 , M = 2010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
ll f[N] ;
ll n , p ;
int main()
{
    cin >> n >> p ;
    f[1] = 1 ;
    
    for(int i = 2 ; i <= n ; i ++)
    {
        
	    for(int j = 1 ; j < i ; j ++)
	    {
	        f[i] = (f[i] + f[j]) % p ;
	    }
        for(int j = 2 ; j <= i ; j ++)
        {
            f[i] = (f[i] + f[i/j]) % p ;
        }
        
    }
    
    cout << f[n] << "\\n" ;
    return 0;
}
时间复杂度 o n^2
肯定过不去

考虑一下第一层循环怎么优化
 for(int j = 1 ; j < i ; j ++)
 {
       f[i] = (f[i] + f[j]) % p ;
 }
 用res表示f[k] [1 <= k < i] 的前缀和
 o1转移即可

在考虑一下第二层的优化

for(int j = 2 ; j <= i ; j ++)
{
    f[i] = (f[i] + f[i/j]) % p ;
}

简化一下就是
f[i/2] + f[i/3] + f[i/4] + ....... + f[i/i]

考虑在加一项
f[i/1]

就变成了
f[i/1] + f[i/2] + f[i/3] + f[i/4] + ....... + f[i/i] - f[i/1]

下面这个式子是整除分块
f[i/1] + f[i/2] + f[i/3] + f[i/4] + ....... + f[i/i]

可以nsqrtn求出来

在减去f[i/1]即可

整除分块

时间复杂度:O nsqrtn

#include<bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define re register int
#define pll pair<int,int> 
#define pb push_back
#define x first 
#define y second 
#define sf(x) scanf("%d",&x)
#define sfl(x) scanf("%lld",&x)
#define de(x) cout << x << "\\n" ;
typedef long long ll ;
using namespace std;
const int N = 1e6 + 10 , M = 2010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
ll f[N] ;
ll n , p ;
int main()
{
    cin >> n >> p ;
    f[1] = 1 ;
    ll cnt = 0 ;
    ll res = f[1] ;
    for(int i = 2 ; i <= n ; i ++)
    {
        f[i] = (f[i] + res) % p ;
        
        ll x = f[i] ;
        cnt = 0 ;
        for(int l = 1 , r ; l <= i ; l = r + 1)
	    {
	        r = i / (i / l) ;
	        cnt = (cnt % p + (r - l + 1) * f[i/l] % p) % p;
	    }
	    
	    f[i] = (f[i] + cnt - x) % p ;
	   
        // for(int j = 2 ; j <= i ; j ++)
        // {
        //     f[i] = (f[i] + f[i/j]) % p ;
        // }
        
        res = (res + f[i]) % p ;
    }
    
    cout << f[n] << "\\n" ;
    return 0;
}

d2变大了n的范围

前缀和可以on
主要是整除分块的 nsqrtn 大概是1e10的时间复杂度
所以过不去

进一步考虑优化
缩进优化(整除分块)
时间复杂度nlogn

目前还不会
待补

以上是关于Codeforces Round #740 (Div. 2) D1. Up the Strip (simplified version)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #740 Div. 2 A B C D1 D2

Codeforces Round #740 Div. 2 A B C D1 D2

Codeforces Round #740 (Div. 2) D1. Up the Strip (simplified version)

Codeforces Round #740 (Div. 2) D1. Up the Strip (simplified version)

Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine))

Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine))ABCD1D2E题解