(数学,大数运算)Consecutively Increasing Sequences_ACdream原创群赛(17)のacmer never retire

来源:互联网 发布:iphone手机阅读软件 编辑:程序博客网 时间:2024/06/05 22:48

E - Consecutively Increasing Sequences

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
SubmitStatus

Problem Description

给出无限长的序列1,1,3,1,3,5,7,1,3,5,7,9,11,13,15,1,3,5,7,9...,问对于序列的前N个数,所有的连续上升子序列的和是多少.
如N = 6的时候,序列是{1,1,3,1,3,5},它的所有连续上升子序列是{1},{1},{1,3},{3},{1},{1,3},{1,3,5},{3},{3,5},{5},结果为39.

Input

多组数据(约1000组),每组数据:

一行N (1 <= N <= 10^9)

Output

对于每个N,输出结果

Sample Input

12610

Sample Output

1239119

Sigma(1..n) = n * (n + 1) / 2

Sigma(1^2 ..n^2) = n * (n + 1) * (2 * n + 1) / 2

Sigma(1^3.. n^3) = n^2*(n + 1)^2 / 4

因为要求序列连续上升,所以只有从1开始的一段才有用,被下一个1隔开的一段完全失效。对于一段从1开始的,我们发现前k项的和是(2 * 1 - 1) + .... + (2 * k - 1) = k^2,所以假设我们枚举每个子序列的终止位置为k的话,枚举它的起始位置为j,那么它们的和就是k ^2-j^2。Sum(k^2 - j^2)(j = 0... k - 1) = k^3 - k * (k - 1) * (2 * k - 1) / 6,然后k从1到序列长度求和即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
usingnamespacestd;
  
constintSIZE = 7;
constintmod = 1000000000;
structbignum
{
    longlonga[SIZE];
    bignum() {
        memset(a,0,sizeof(a));
    }
      
    bignum(longlongn) {
        memset(a,0,sizeof(a));
        a[0] = n;
        adjust();
    }
          
    bignum adjust() {
        for(inti = 0; i < SIZE; i ++)
            if(a[i] >= mod) {
                a[i + 1] += a[i] / mod;
                a[i] %= mod;
            }
            elseif(a[i] < 0) {
                a[i + 1] --;
                a[i] += mod;
            }
    }
      
    bignum operator * (constbignum &p) {
        bignum c;
        for(inti = 0; i < SIZE; i ++)
            for(intj = 0; i + j < SIZE; j ++)
                c.a[i + j] += a[i] * p.a[j];
        c.adjust();
        returnc;
    }
      
    bignum operator / (constintx) {
        longlongtmp = 0;
        bignum c;
        memcpy(c.a,a,sizeof(a));
        for(inti = SIZE - 1; i >= 0; i --) {
            longlongp = (tmp * mod + c.a[i]) % x;
            c.a[i] = (tmp * mod + c.a[i]) / x;
            tmp = p;
        }
        returnc;
    }
      
    bignum operator + (bignum &p) {
        bignum c;
        for(inti = 0; i < SIZE; i ++)
            c.a[i] = a[i] + p.a[i];
        c.adjust();
        returnc;
    }
      
    bignum operator - (bignum &p) {
        bignum c;
        for(inti = 0; i < SIZE; i ++)
            c.a[i] = a[i] - p.a[i];
        c.adjust();
        returnc;
    }
      
    booloperator == (bignum &p) {
        for(inti = 0; i < SIZE; i ++)
            if(a[i] != p.a[i]) returnfalse;
        returntrue;
    }
      
    voidoutput() {
        inti = SIZE - 1;
        for(i; i >= 0; i --) {
            if(a[i]) break;
        }
        printf("%lld",a[i]);
        for(i = i - 1; i >= 0; i --)
            printf("%09lld",a[i]);
        printf("\n");
    }
};
  
bignum cal1(intn)
{
    returnbignum(n) * bignum(n + 1) / 2;
}
  
bignum cal2(intn)
{
    returnbignum(n) * bignum(n + 1) * bignum(2 * n + 1) / 6;
}
  
bignum cal3(intn)
{
    returnbignum(n) * bignum(n) * bignum(n + 1) * bignum(n + 1) / 4;
}
  
bignum cal(intn)
{
    bignum tot = cal3(n);
    bignum sub1 = bignum(2) * cal3(n);
    bignum sub2 = bignum(3) * cal2(n);
    bignum sub3 = cal1(n);
    sub1 = sub1 + sub3;
    sub1 = sub1 - sub2;
    sub1 = sub1 / 6;
    returntot - sub1;
}
  
longlongbaoli(intn)
{
    longlongans = 0;
    intnow = 0;
    while(n) {
        intm = min(1 << now,n);
        n -= m;
        for(longlongi = 1; i <= m; i ++)
            for(longlongj = 0; j < i; j ++)
                ans += i * i - j * j;
        now ++;
    }
    returnans;
}
  
voidsolve(intn)
{
    //int tn = n;
    bignum ans;
    intnow = 0;
    while(n) {
        intm = min(1 << now,n);
        n -= m;
        bignum tmp = cal(m);
        now ++;
        ans = ans + tmp;
    }
    ans.output();
    //long long tans = baoli(tn);
    //bignum test = bignum(tans);
}
  
intmain()
{
    intn;
    while(scanf("%d",&n) != EOF) solve(n);
    return0;
}



0 0
原创粉丝点击