zoukankan      html  css  js  c++  java
  • Codeforces 1105C (dp)

    传送门

    题意:

    有一个长度为nn的数列的未知数列,数列的每一个数的值都在区间[l,r][l,r]的范围内。现在问你能够构成多少个这样的数组,使得数组内的所有数的和能够被33整除。

    题目分析:

    在这个题中,我们不能纠结在具体的数值的变化,我们需要关注数量的变化。

    首先,涉及到这类整除性的问题,我们需要将它转化成余数的问题。那么我们可以发现,这些数的余数只会在[0,2][0,2]的范围之间变化,因此我们只需分别考虑这三种情况。

    我们考虑这样一个问题。如果一个数xx能够被33整除,则我们设x=3kx=3k。而因为lxrlle x le r,则我们有l3kr3frac{l}{3}le kle frac{r}{3}。则易得,能被33整除的数的个数为:r3l3frac{r}{3}-frac{l}{3}

    同理有,模3311的个数为:r13l13frac{r-1}{3}-frac{l-1}{3}

    3322的个数为:r23l23frac{r-2}{3}-frac{l-2}{3}

    得到个数之后,我们就可以用dpdp对答案进行转移。

    我们设dp[i][j]dp[i][j]为数列的前ii个数字被取了后,余数为jj的方案数,cnt[i]cnt[i]为在区间[l,r][l,r]中,模33ii的个数。

    则我们容易发现,当前的状态,是由前一个状态分别加上余00,余11,余22的方案数转移过来的,即有状态转移方程:dp[i][j+k]+=dp[i1][j]cnt[k]dp[i][j+k]+=dp[i-1][j]*cnt[k]

    因此我们可以用O(n)mathcal{O}(n)的时间复杂度进行转移,最终的答案即为dp[n][0]dp[n][0]

    #include <bits/stdc++.h>
    #define maxn 200005
    
    using namespace std;
    typedef long long ll;
    ll dp[maxn][3];
    const int mod=1e9+7;
    int main()
    {
        int n,l,r;
        scanf("%d%d%d",&n,&l,&r);
        l--;
        dp[0][0]=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<3;j++){
                ll w=(r-j+3)/3-(l-j+3)/3;
                for(int k=0;k<3;k++){
                    dp[i+1][(k+j)%3]=(dp[i+1][(k+j)%3]+dp[i][k]*w)%mod;
                }
            }
        }
        cout<<dp[n][0]<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    基本语法-函数
    基本语法-变量
    python+selenium2自动化------quit()和close()区别
    docker搭建bwapp漏洞测试环境
    软件测试---登录功能的测试用例
    Faker开源库构造测试数据
    selenium自动化简易测试框架总结
    ddt+unittest+HTMLTestRunner,生成测试报告时,报告中没有输出测试用例函数的描述信息
    python+selenium2自动化---PageObject模式+unittest结合实现自动化
    python+selenium2自动化---关键字驱动+unittest结合实现自动化
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007164.html
Copyright © 2011-2022 走看看