CF1105C Ayoub and Lost Array ——动态规划

CF1105C Ayoub and Lost Array

题意:
一个整数数组,满足:
1. 长度为n
2. 所有元素都在[l, r]范围内
3. 所有元素的和能被3整除
给出n, l, r (1 ≤ n ≤ 2*10^5,1 ≤ l ≤ r ≤ 10^9)
请找出符合条件的数组的个数,答案对 10^9 + 7取模

首先我们要处理出[l, r]中对3取模得结果分别为0,1,2的数的个数,在一个合乎要求的数组中,结果为1和2的数的个数必然一样,由此就可以很方便地得到所有可能的组合的个数。但新的问题来了,由于可以选用相同的数,求出这些组合的排列数几乎是一个不可能完成的任务(对我这种蒟蒻来说)。
换一种思路,我们一个数一个数地添,并把所有可能的情况都考虑进去:
设dp[i][j]表示有i个数,且它们的和对3取模结果为j的数组个数,数组num[i]中记录了[l, r]中对3取模得结果为i的数的个数
显然dp[1][j] = num[j],随后,向已有的数组的尾部添加新的数字,例如:
dp[i][0] = dp[i - 1][0] * num[0] + dp[i - 1][1] * num[2] + dp[i - 1][2] * num[1]
dp[i][1]和dp[i][2]的情况同理,递推到n,dp[n][0]就是我们要的答案。

为什么是添加到尾部?不能插入到某个数字前吗?这样做会不会漏情况?
实际上,插入到某个数字之前会带来重复(会有另一个数被顶到尾部),举个例子:现在前i - 1个数的和对3取模结果为1,要添加一个结果为2的数,即dp[i - 1][1] * num[2],如果把它插入到前面,使一个对3取模结果为1的数被顶到了前面的话,显然就与dp[i - 1][2] * num[1]的情况重复了,另外两种情况同理。

附关键部分代码,欢迎纠错。

const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
ll dp[maxn][3];//有i个数,且它们的和对3取模结果为j的数组个数
int main()
{
    //num[i]记录了对3取模结果为i的数的个数
    dp[1][0] = num[0], dp[1][1] = num[1], dp[1][2] = num[2];
    for(int i = 2; i <= n; i++)
    {
        dp[i][0] = (dp[i - 1][0] * num[0]) % mod + (dp[i - 1][1] * num[2]) % mod + (dp[i - 1][2] * num[1]) % mod;
        dp[i][0] %= mod;
        dp[i][1] = (dp[i - 1][0] * num[1]) % mod + (dp[i - 1][1] * num[0]) % mod + (dp[i - 1][2] * num[2]) % mod;
        dp[i][1] %= mod;
        dp[i][2] = (dp[i - 1][0] * num[2]) % mod + (dp[i - 1][1] * num[1]) % mod + (dp[i - 1][2] * num[0]) % mod;
        dp[i][2] %= mod;
    }
    cout << dp[n][0] << endl;
}

原文地址:https://www.cnblogs.com/sun-of-Ice/p/10301905.html

时间: 2024-08-06 08:23:55

CF1105C Ayoub and Lost Array ——动态规划的相关文章

C. Ayoub and Lost Array cf dp

C. Ayoub and Lost Array time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Ayoub had an array aa of integers of size nn and this array had two interesting properties: All the integers in the a

Codeforces Round #533 (Div. 2)C. Ayoub and Lost Array

C. Ayoub and Lost Array Ayoub had an array ?? of integers of size ?? and this array had two interesting properties: All the integers in the array were between ?? and ?? (inclusive). The sum of all the elements was divisible by 3. Unfortunately, Ayoub

CF1105C 【Ayoub and Lost Array】

简单\(\text{dp}\) 我们设\(\text{dp[i][j]}\)表示前\(\text{i}\)位除以\(\text{3}\)的余数为\(\text{j}\)的个数,那么可以明显的推出状态转移方程 \(\text{dp[i][0]=dp[i-1][1]*mod[2]+dp[i-1][2]*mod[1]+dp[i-1][0]*mod[0]}\) \(\text{dp[i][1]=dp[i-1][0]*mod[1]+dp[i-1][1]*mod[0]+dp[i-1][2]*mod[2]}\

C. Ayoub and Lost Array Round #533 (Div. 2) 【DP】

一.题面 链接 二.分析 关于这题,两个点. 第一个点,是需要能够分析出$[L,R]$区间的3的余数的个数. 首先,可以得到,$[L,R]$区间内共有$(R-L+1)$个数. 设定余数为0,1,2的为一组,那么1,2,0和2,0,1也是一组.那么可以肯定能得到$(R-L+1)/3$组. 那么还余下了$(R-L+1)%3$个数.这里就需要考虑从$L$开始往右移$(R-L+1)%3$个数,分析这几个数的余数即可.因为这几个数后的数肯定是能分成3个一组的. 第二个点,用DP的思维去求解. 区间内的数能

C - Ayoub and Lost Array

#include<iostream> #include<cstdio> #define maxn 200007 const int mod=1e9+7; typedef long long ll; using namespace std; ll dp[maxn][3]; int n,l,r; int main() { int x,y,z; cin>>n>>l>>r; x=r/3-(l-1)/3,y=(r+2)/3-(l+1)/3,z=(r+1)/

Codeforces 1105C Ayoub and Lost Array

题目大意: 一个长度为$n$的数组,其和能被$3$整除,且每一个数字满足$a_{i}\in [l,r]$,问有多少种可以满足上述三个条件的数组 分析: $dp$.$dp[i][j]=$前$i$个数构成余数为$j$的方案数,然后通过这个$dp$的定义,可以推出递推方程$dp[i][j]=\sum_{i}^{2}dp[i][(j+k)%3]*n[k]$,其中$n[k]$为满足数字$a_{i}\in [l,r]$余数为$k$的个数,而$n[k]$的求法也很简单,以余数为$1$为例,假设$a_{i}=3

codeforces round 533 div2 C Ayoub and Lost Array [dp]

一道思维题 不仅是和这道题在战斗,我和编译器也进行了一场激烈的角逐 因为编译器出了点小问题... 对于dev或者codeblocks 我的方法是卸载了重新装/重启电脑 但是对于vscode 我的方法是, 对着它掉眼泪,看它能不能可怜可怜我,赶紧恢复到正常状态.... #include<bits/stdc++.h> using namespace std; typedef long long ll; //#define int long long const ll N = 2e5 + 1000;

Codeforces Round #533 (Div. 2)

A. Salem and Sticks 由于长度很小,所以直接暴力枚举最后的长度即可,取最小值即可. #include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)); using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=10010; int a[1100],n; int cost,ans; int main(){ ci

Codeforces Round #533 (Div. 2) Solution

A. Salem and Sticks 签. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 int n, a[N]; 6 7 int work(int x) 8 { 9 int res = 0; 10 for (int i = 1; i <= n; ++i) 11 res += max(0, abs(x - a[i]) - 1); 12 return res; 13 } 14 15 int m