题面:

传送门

题目描述:

题意很简单:1.数组中的所有整数都在区间[l, r],2.所有元素之和能被3整除。现在知道这个数组的大小,l和r,问:按照题目的要求组成的数组一共有多少种可能。
 

题目分析:

这道题应该是一道常见的用dp来解决计数的问题。
1.如果忽略所有元素之和能被3整除,那么,按照正常的想法答案肯定是:(r-l+1)n。但是题目多了所有元素之和能被3整除,看似难度大了很多。其实,我们可以分析一下:忽略所有元素之和能被3整除,答案是怎样想出来的:每一个“位”上都有(r-l+1)种选择,然后把每个“位”上的选择乘起来,就是(r-l+1)n。因此,我们可以通过研究每个"位"上的选择来解决这个问题。但在实际情况中,这个“位”的选择实在是不好解决:要确定所有元素之和要被3整除,有些“位”可能是之前不能被3整除,经过几次累加后就能被3整除了,情况过于复杂。这时,我们要想一种能“简化过程”的思想:
把问题拆解子问题,对应的解决办法其中就有dp。我们可以这样定义问题:前n个数的和能被3模余p(p = 0, 1, 2)的可能有多少?那么其中一个子问题是:前n-1个数的和能被3模余p(p = 0, 1, 2)的可能有多少?换成更直观的图,其实就是:
前n-1位已经确定好(计算出前n-1位的可能数),如果确定了第n位的选择,那么根据组合数学计数原理,就可以用前n-1位计算出的结果计算出前n位一共有多少种选择。第n位的选择要看当前的“状态”是什么:也就是和p有关。
 
2.经过分析,有如下选择(这里用dp[p][n]来代表上面的含义):
当p == 0时:
dp[0][n] += dp[0][n-1] * (第n位选被3模后余数为0的数的个数)
dp[0][n] += dp[1][n-1] * (第n位选被3模后余数为2的数的个数)
dp[0][n] += dp[2][n-1] * (第n位选被3模后余数为1的数的个数)
 
当p == 1时:
dp[0][n] += dp[0][n-1] * (第n位选被3模后余数为1的数的个数)
dp[0][n] += dp[1][n-1] * (第n位选被3模后余数为0的数的个数)
dp[0][n] += dp[2][n-1] * (第n位选被3模后余数为2的数的个数)
 
当p == 2时:
dp[0][n] += dp[0][n-1] * (第n位选被3模后余数为2的数的个数)
dp[0][n] += dp[1][n-1] * (第n位选被3模后余数为1的数的个数)
dp[0][n] += dp[2][n-1] * (第n位选被3模后余数为0的数的个数)
我们先看看当p == 0时,是怎样得到结果的:有三种情况:第一种情况:前n-1个数的和取模后余数为0且第n个数选余数为0的数,这样才能保证前n位之和取模后余数为0(也就是p);第二种情况:前n-1个数的和取模后余数为1且第n个数选余数为2的数,这样才能保证前n位之和取模后余数为0(也就是p);第三种情况同理可得,p == 1和p == 2也同理可得。
 
3.现在的问题关键是:第n位选被3模后余数为p的数的个数怎么算:我们可以思考这样一个问题:1-x中,被3取模后余数为p的数的个数 fp(x) 是多少?假如我们解决这个问题,就可以用 fp(r) - fp(l-1) 来算出答案了。因为p的选择不多(p = 0, 1, 2),所以我们直接分类讨论就行了:
1-x中,被3取模后余数为0的数的个数:f0(x) = x / 3
1-x中,被3取模后余数为1的数的个数:f1(x) = (x + 2) / 3
1-x中,被3取模后余数为2的数的个数:f2(x) = (x + 1) / 3
 
4.自己注意初始化问题。
 
 
AC代码:
 1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <cmath>
5 #include <algorithm>
6 using namespace std;
7 const long long mod = 1e9+7;
8 const long long maxn = 2e5+5;
9 long long n, l, r;
10
11 long long dp[5][maxn];
12
13 const int yu[3][3] = {{0, 2, 1}, {1, 0, 2}, {2, 1, 0}};
14
15
16 int main(){
17 cin >> n >> l >> r;
18 int t;
19
20 //注意初始化
21 for(int i = 0; i < 3; i++){
22 t = (3-i)%3;
23 dp[i][1] = ( (r+t)/3-(l+t-1)/3 );
24 }
25
26
27 for(int i = 2; i <= n; i++){
28 for(int k = 0; k < 3; k++){
29 for(int p = 0; p < 3; p++){
30 t = (3-yu[k][p]) % 3;
31 dp[k][i] += dp[p][i-1]*( (r+t)/3-(l+t-1)/3 ) % mod;
32 dp[k][i] %= mod;
33 }
34 }
35 }
36
37 cout << dp[0][n] << endl;
38
39 return 0;
40 }
 
 
 
 

Codeforces Round #533 C. Ayoub and Lost Array的更多相关文章

  1. Codeforces Round #533 (Div. 2)题解

    link orz olinr AK Codeforces Round #533 (Div. 2) 中文水平和英文水平都太渣..翻译不准确见谅 T1.给定n<=1000个整数,你需要钦定一个值t, ...

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

    传送门:http://codeforces.com/contest/1105/problem/C C. Ayoub and Lost Array time limit per test 1 secon ...

  3. Codeforces Round #533 (Div. 2) C.思维dp D. 多源BFS

    题目链接:https://codeforces.com/contest/1105 C. Ayoub and Lost Array 题目大意:一个长度为n的数组,数组的元素都在[L,R]之间,并且数组全 ...

  4. Codeforces Round #533 (Div. 2) Solution

    A. Salem and Sticks 签. #include <bits/stdc++.h> using namespace std; #define N 1010 int n, a[N ...

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

    链接:https://codeforces.com/contest/1105/problem/C 题意: 给n,l,r. 一个n长的数组每个位置可以填区间l-r的值. 有多少种填法,使得数组每个位置相 ...

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

    题意: 长为 n,由 l ~ r 中的数组成,其和模 3 为 0 的数组数目. 思路: dp[ i ][ j ] 为长为 i,模 3 为 j 的数组数目. #include <bits/stdc ...

  7. Codeforces Round #258 (Div. 2) . Sort the Array 贪心

    B. Sort the Array 题目连接: http://codeforces.com/contest/451/problem/B Description Being a programmer, ...

  8. Codeforces Round #555 (Div. 3) E. Minimum Array 【数据结构 + 贪心】

    一 题面 E. Minimum Array 二 分析 注意前提条件:$0 \le  a_{i} \lt n$ 并且 $0 \le  b_{i} \lt n$.那么,我们可以在$a_{i}$中任取一个数 ...

  9. Codeforces Round #533 (Div. 2) B. Zuhair and Strings 【模拟】

    传送门:http://codeforces.com/contest/1105/problem/B B. Zuhair and Strings time limit per test 1 second ...

随机推荐

  1. VS2010的单元测试(二)

    四.附加测试属性 附加测试属性,在默认生成的测试代码是使被注释掉的,取消注释就可以使用. 例如,要在执行测试前,输出测试开始时间,在执行测试后,输出测试结束时间.代码如下: [ClassInitial ...

  2. Leetcode(8)-字符串转整数

    实现 atoi,将字符串转为整数. 在找到第一个非空字符之前,需要移除掉字符串中的空格字符.如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即为整数的值 ...

  3. MD5强碰撞

    关卡一         md5弱比较,为0e开头的会被识别为科学记数法,结果均为0 payload param1=QNKCDZO&param2=aabg7XSs 关卡二         md5 ...

  4. 还傻傻分不清楚equals和==的区别吗?看完就明白了

    解决一个问题的最好方法就是发现一个问题产生的根源,即发现最本质的东西,再去解决它. Java语言里面的equals()方法是交给开发者们自己去覆盖重写编写功能的,即让开发者去定义当满足什么条件时,两个 ...

  5. 使用 js 实现一个简易版的 GIPHY 动图搜索 web 应用程序

    使用 js 实现一个简易版的 GIPHY 动图搜索 web 应用程序 具有挑战性的前端面试题 API JAMstack refs https://www.infoq.cn/article/0NUjpx ...

  6. how to create react custom hooks with arguments

    how to create react custom hooks with arguments React Hooks & Custom Hooks // reusable custom ho ...

  7. asm 查看字节码

    a.asm global Start section .text inc dword [esi] push edi mov edi,[esp+0x14] λ nasm -f win32 a.asm - ...

  8. Flutter: MobX和flutter_mobx状态管理器

    MobX.dart网站上的 " 入门指南" mobxjs video 组织Stores 安装依赖 dependencies: mobx: flutter_mobx: dev_dep ...

  9. 「NGK每日快讯」11.18日NGK公链第15期官方快讯

  10. 12.scikit-learn中的Scaler

    import numpy as np from sklearn import datasets iris = datasets.load_iris() X = iris.data y = iris.t ...