codeforce C. Ayoub and Lost Array

C. Ayoub and Lost Arraytime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputAyoub had an array aa of integers of size nn and this array had two interesting properties:All the integers in the array were between ll and rr (inclusive).The sum of all the elements was divisible by 33.Unfortunately, Ayoub has lost his array, but he remembers the size of the array nn and the numbers ll and rr, so he asked you to find the number of ways to restore the array.Since the answer could be very large, print it modulo 109+7109+7 (i.e. the remainder when dividing by 109+7109+7). In case there are no satisfying arrays (Ayoub has a wrong memory), print 00.InputThe first and only line contains three integers nn, ll and rr (1≤n≤2⋅105,1≤l≤r≤1091≤n≤2⋅105,1≤l≤r≤109) — the size of the lost array and the range of numbers in the array.OutputPrint the remainder when dividing by 109+7109+7 the number of ways to restore the array.ExamplesinputCopy2 1 3
outputCopy3
inputCopy3 2 2
outputCopy1
inputCopy9 9 99
outputCopy711426616
NoteIn the first example, the possible arrays are : [1,2],[2,1],[3,3][1,2],[2,1],[3,3].In the second example, the only possible array is [2,2,2][2,2,2].
题意:题目中的意思简单介绍就是从l~r中找出大小为n的一个数组,数组的和能够被3整除。
题解:这样的题目一看就是递推完成的题目。递推的过程就是完成每一个的数字的放置的过程。递推的标志也非常的明显,递推的情况一般能够通过有限种类数量来表示,这个题目的余数有三种情况:分别是0,1,2;加数的余数也有三种情况:0,1,2;也就是总共有9种情况:
加数,余数 --下标
0,0 --1
0,1 --2
0,2 --3
1,0 --4
1,1 --5
1,2 --6
2,0 --7
2,1 --8
2,2 --9
下面推出情况:
tab[i][1] = (tab[i-1][1]+tab[i-1][4]+tab[i-1][7])*num[0];
tab[i][5] = (tab[i-1][1]+tab[i-1][4]+tab[i-1][7])*num[1];
tab[i][9] = (tab[i-1][1]+tab[i-1][4]+tab[i-1][7])*num[2];
tab[i][2] = (tab[i-1][2]+tab[i-1][5]+tab[i-1][8])*num[0];
tab[i][6] = (tab[i-1][2]+tab[i-1][5]+tab[i-1][8])*num[1];
tab[i][7] = (tab[i-1][2]+tab[i-1][5]+tab[i-1][8])*num[2];
tab[i][3] = (tab[i-1][3]+tab[i-1][6]+tab[i-1][9])*num[0];
tab[i][4] = (tab[i-1][3]+tab[i-1][6]+tab[i-1][9])*num[1];
tab[i][8] = (tab[i-1][3]+tab[i-1][6]+tab[i-1][9])*num[2];
num【i】是表示余数为i的可取数字的个数,这就是通过i-1次推到i次的过程,如果不理解的话,多画画图,都列出来然后进行合并就可以了。
下面列出代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 1e6;
int n,l,r;
long long mod = 1e9+7;
long long tab[MAXN][15];
long long num[5];
int main()
{
    scanf("%d%d%d",&n,&l,&r);
    for(int i=0;i<4;i++){
        num[i] = 0;
    }
    for(int i=0;i<14;i++){
        tab[0][i] = 0;
    }
    num[1] = num[0] = num[2] = (r-l+1)/3;
    for(int i=l,j=0;j<(r-l+1)%3;i++,j++){
        num[i%3]++;
    }
    tab[0][1] = num[0];
    tab[0][5] = num[1];
    tab[0][9] = num[2];
    for(int i=1;i<n;i++){
        tab[i][1] = (tab[i-1][1]+tab[i-1][4]+tab[i-1][7])*num[0];
        tab[i][5] = (tab[i-1][1]+tab[i-1][4]+tab[i-1][7])*num[1];
        tab[i][9] = (tab[i-1][1]+tab[i-1][4]+tab[i-1][7])*num[2];
        tab[i][2] = (tab[i-1][2]+tab[i-1][5]+tab[i-1][8])*num[0];
        tab[i][6] = (tab[i-1][2]+tab[i-1][5]+tab[i-1][8])*num[1];
        tab[i][7] = (tab[i-1][2]+tab[i-1][5]+tab[i-1][8])*num[2];
        tab[i][3] = (tab[i-1][3]+tab[i-1][6]+tab[i-1][9])*num[0];
        tab[i][4] = (tab[i-1][3]+tab[i-1][6]+tab[i-1][9])*num[1];
        tab[i][8] = (tab[i-1][3]+tab[i-1][6]+tab[i-1][9])*num[2];
        for(int j=1;j<=9;j++){
            tab[i][j] = tab[i][j]%mod;
            //printf("%I64d",tab[i][j]);
        }
        //printf("\n");
    }
    long long resu = 0;
    resu = resu+tab[n-1][1];
    resu%=mod;
    resu = resu+tab[n-1][4];
    resu%=mod;
    resu = resu+tab[n-1][7];
    resu%=mod;
    //printf("%d %d %d\n",num[0],num[1],num[2]);
    printf("%I64d\n",resu);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40488730/article/details/86570129