2016 Multi-University Training Contest 1 H.Shell Necklace

Shell Necklace

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 534    Accepted Submission(s): 227

Problem Description

Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n beautiful shells contains the most sincere feeling for my best lover Arrietty, but even that is not enough.

Suppose the shell necklace is a sequence of shells (not a chain end to end). Considering i continuous shells in the shell necklace, I know that there exist different schemes to decorate the i shells together with one declaration of love.

I want to decorate all the shells with some declarations of love and decorate each shell just one time. As a problem, I want to know the total number of schemes.

Input

There are multiple test cases(no more than 20 cases and no more than 1 in extreme case), ended by 0.

For each test cases, the first line contains an integer n, meaning the number of shells in this shell necklace, where 1≤n≤105. Following line is a sequence with nnon-negative integer a1,a2,…,an, and ai≤107 meaning the number of schemes to decorate i continuous shells together with a declaration of love.

Output

For each test case, print one line containing the total number of schemes module 313(Three hundred and thirteen implies the march 13th, a special and purposeful day).

Sample Input

3
1 3 7
4
2 2 2 2
0

Sample Output

14
54

Hint

For the first test case in Sample Input, the Figure 1 provides all schemes about it. The total number of schemes is 1 + 3 + 3 + 7 = 14.

Author

HIT

题意:
    一串由n颗珍珠组成的项链,连续的i个珍珠有ci种染色方式。
    问n颗珍珠有多少种染色方式?
题解:
    显然可知dp方程
    f[i] = sigma(f[i - j] * a[j])
    由于n很大,可以考虑分治fft解决。

    说说这个分治fft:
    如果我们需要计算出l~r的f的值。
    假设我们已经计算出(l,mid)的f的值
    观察方程
    f[i] = sigma(f[j] * a[i - j]) 1 <= j < i
        = sigma(f[j] * a[i - j]) + sigma(f[k] * a[i - k])   1<= j <= mid, mid < k < i
    所以可以分开计算f[l~mid]对f[mid+1~r]的影响。
    具体过程可以看代码。
    使用时记得调整一下下标。

  

  1 class Complex {
  2     public :
  3         double real, image;
  4
  5         Complex(double real = 0., double image = 0.):real(real), image(image) {}
  6         Complex(const Complex &t):real(t.real), image(t.image) {}
  7
  8         Complex operator +(const Complex &t) const {
  9             return Complex(real + t.real, image + t.image);
 10         }
 11
 12         Complex operator -(const Complex &t) const {
 13             return Complex(real - t.real, image - t.image);
 14         }
 15
 16         Complex operator *(const Complex &t) const {
 17             return Complex(real * t.real - image * t.image,
 18                         real * t.image + t.real * image);
 19         }
 20 };
 21
 22 const int N = 300010, MOD = 313;
 23 const double PI = acos(-1.);
 24
 25 class FFT {
 26     /**
 27      * 1. Need define PI
 28      * 2. Need define class Complex
 29      * 3. tmp is need for fft, so define a N suffice it
 30      * 4. dig[30] -> (1 << 30) must bigger than N
 31      * */
 32     private :
 33         static Complex tmp[N];
 34         static int revNum[N], dig[30];
 35
 36     public :
 37         static void init(int n) {
 38             int len = 0;
 39             for(int t = n - 1; t; t >>= 1) ++len;
 40             for(int i = 0; i < n; i++) {
 41                 revNum[i] = 0;
 42                 for(int j = 0; j < len; j++) dig[j] = 0;
 43                 for(int idx = 0, t = i; t; t >>= 1) dig[idx++] = t & 1;
 44                 for(int j = 0; j < len; j++)
 45                     revNum[i] = (revNum[i] << 1) | dig[j];
 46             }
 47         }
 48
 49         static int rev(int x) {
 50             return revNum[x];
 51         }
 52
 53         static void fft(Complex a[], int n, int flag) {
 54             /**
 55              * flag = 1 -> DFT
 56              * flag = -1 -> IDFT
 57              * */
 58             for(int i = 0; i < n; ++i) tmp[i] = a[rev(i)];
 59             for(int i = 0; i < n; ++i) a[i] = tmp[i];
 60             for(int i = 2; i <= n; i <<= 1) {
 61                 Complex wn(cos(2 * PI / i), flag * sin(2 * PI / i));
 62                for(int k = 0, half = i / 2; k < n; k += i) {
 63                    Complex w(1., 0.);
 64                    for(int j = k; j < k + half; ++j) {
 65                        Complex x = a[j], y = w * a[j + half];
 66                        a[j] = x + y, a[j + half] = x - y;
 67                        w = w * wn;
 68                    }
 69                }
 70             }
 71             if(flag == -1) {
 72                 for(int i = 0; i < n; ++i) a[i].real /= n;
 73             }
 74         }
 75
 76         static void dft(Complex a[], int n) {
 77             fft(a, n, 1);
 78         }
 79
 80         static void idft(Complex a[], int n) {
 81             fft(a, n, -1);
 82         }
 83 };
 84 Complex FFT::tmp[N];
 85 int FFT::revNum[N], FFT::dig[30];
 86
 87 int n, arr[N];
 88 int f[N];
 89 Complex A[N], B[N];
 90
 91 inline void divideAndConquer(int lef, int rig) {
 92     if(lef >= rig) return;
 93     int mid = (lef + rig) >> 1;
 94     divideAndConquer(lef, mid);
 95
 96     int m;
 97     for(m = 1; m < (rig - lef + 1) * 2; m <<= 1);
 98     for(int i = 0; i < m; ++i) A[i] = B[i] = Complex();
 99     for(int i = lef; i <= mid; ++i) A[i - lef] = Complex(f[i]);
100     int len = min(n, m - 1);
101     for(int i = 0; i < len; ++i) B[i + 1] = Complex(arr[i]);
102     FFT::init(m);
103     FFT::dft(A, m), FFT::dft(B, m);
104     for(int i = 0; i < m; ++i) A[i] = A[i] * B[i];
105     FFT::idft(A, m);
106
107     for(int i = mid + 1; i <= rig; ++i)
108         f[i] = (f[i] + ((ll)(A[i - lef].real + 0.5))) % MOD;
109
110     divideAndConquer(mid + 1, rig);
111 }
112
113 inline void solve() {
114     for(int i = 0; i < n; ++i) arr[i] %= MOD;
115     for(int i = 0; i <= n; ++i) f[i] = 0;
116     f[0] = 1;
117     divideAndConquer(0, n);
118
119     printf("%d\n", f[n]);
120 }
121
122 int main() {
123     while(scanf("%d", &n) == 1 && n) {
124         for(int i = 0; i < n; ++i) scanf("%d", &arr[i]);
125         solve();
126     }
127     return 0;
128 }

时间: 2024-10-27 03:24:27

2016 Multi-University Training Contest 1 H.Shell Necklace的相关文章

hdu 5775 Bubble Sort(2016 Multi-University Training Contest 4——树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5775 Bubble Sort Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 636    Accepted Submission(s): 378 Problem Description P is a permutation of the

hdu 5802 Windows 10(2016 Multi-University Training Contest 6——贪心+dfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5802 Windows 10 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1005    Accepted Submission(s): 333 Problem Description Long long ago, there was a

hdu 5792 World is Exploding(2016 Multi-University Training Contest 5——树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5792 World is Exploding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 643    Accepted Submission(s): 306 Problem Description Given a sequence A

hdu 5821 Ball(2016 Multi-University Training Contest 8——贪心+排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5821 Ball Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 515    Accepted Submission(s): 309 Problem Description ZZX has a sequence of boxes numbe

hdu 5774 Where Amazing Happens(2016 Multi-University Training Contest 4——打表)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5774 Where Amazing Happens Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 443    Accepted Submission(s): 300 Problem Description As the premier m

HDU 6049 - Sdjpx Is Happy | 2017 Multi-University Training Contest 2

思路来源于 FXXL - - 一个比较奇怪的地方就是第三步可以不做,也就是ans至少为1,听说场内有提问的,然后 admin 说可以不做- - (wa的我心烦) /* HDU 6049 - Sdjpx Is Happy [ 枚举,剪枝 ] | 2017 Multi-University Training Contest 2 题意: 长度为N的排列 N <= 3000 排序分三个步骤: 1.原数组分为不相交的K段 2.每段都独立排序 3.选择其中两段swap 问按步骤能成功排序的K能取到的最大是多

2015 Multi-University Training Contest 10 hdu 5406 CRB and Apple

CRB and Apple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 421    Accepted Submission(s): 131 Problem Description In Codeland there are many apple trees.One day CRB and his girlfriend decide

HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Alice and Bob are playing together. Alice is crazy about art and she has visited many museums around the world. She has

【2014 Multi-University Training Contest 3 1002】/【HDU 4888】 Redraw Beautiful Drawings

不容易啊,终于可以补第二个题了!! 顺便说一句:模版写残了就不要怪出题人啊 ~ (这残废模版研究了好长时间才找出错) 题目大意: 有一个n*m的矩阵,每一个格子里都将有一个数.给你每一行数字之和和每一列数字之和.求每一个位置能填0~k之间的哪个数.如果有多种可能输出"Not Unique",如果没有解输出"Impossible",如果一组解则将其输出. 解题思路: 最大流: 不可能的条件:是行之和和列之和不想等或者建图后的最大流与他们不想等. 多组的条件是:在最大流