NAIPC 2016 K-Inversions I-Tourists

Posted tcctw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NAIPC 2016 K-Inversions I-Tourists相关的知识,希望对你有一定的参考价值。

K-Inversions

题意:给定一个只包含A和B的字符串,对于1 <= i < j <= n,如果s[i] = ‘B‘, s[j] = ‘A’, 且j-i=k, 那么就构成了一个k-inversions,对于在1~n-1范围内的k,输出k-inversions的数量

思路:构造两个多项式,A和B,当s[i] == ‘B‘时,A[i] = Complex(0, 0); B[n-i-1] = Complex(1, 0); 当s[i] == ‘A‘时,A[i] = Complex(1, 0); B[n-i-1] = Complex(0, 0); 然后用FFT加速卷积C=A*B, 答案就是C[n...n*2-1],可以用笔推算一下为什么

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const double PI = acos(-1.0);
 4 const int maxn = 2001000;
 5 struct Complex {
 6     double x, y;
 7     Complex(double _x = 0.0, double _y = 0.0)
 8     {
 9         x = _x;
10         y = _y;
11     }
12     Complex operator - (const Complex & b) const
13     {
14         return Complex(x-b.x, y-b.y);
15     }
16     Complex operator + (const Complex & b) const
17     {
18         return Complex(x+b.x, y+b.y);
19     }
20     Complex operator * (const Complex & b) const
21     {
22         return Complex(x*b.x-y*b.y, x*b.y+y*b.x);
23     }
24 };
25 void change(Complex y[], int len)
26 {
27     int i, j, k;
28     for(i = 1, j = len/2; i < len-1; i++) {
29         if(i < j)
30             swap(y[i], y[j]);
31         k = len/2;
32         while(j >= k) {
33             j -= k;
34             k /= 2;
35         }
36         if(j < k)
37             j += k;
38     }
39 }
40 void fft(Complex y[], int len, int on)
41 {
42     change(y, len);
43     for(int h = 2; h <= len; h <<= 1) {
44         Complex wn(cos(-on*2*PI/h), sin(-on*2*PI/h));
45         for(int j = 0; j < len; j += h) {
46             Complex w(1, 0);
47             for(int k = j; k < j+h/2; k++) {
48                 Complex u = y[k];
49                 Complex t = w*y[k+h/2];
50                 y[k] = u+t;
51                 y[k+h/2] = u-t;
52                 w = w*wn;
53             }
54         }
55     }
56     
57 }
58 
59 
60 char s[maxn];
61 Complex A[maxn*2], B[maxn*2];
62 
63 int main()
64 {
65     scanf("%s", s);
66     int n = strlen(s);
67     int len = 1;
68     while(len < n*2)
69         len <<= 1;
70     for(int i = 0; i < n; i++) {
71         if(s[i] == B) {
72             A[i] = Complex(0, 0);
73             B[n-i-1] = Complex(1, 0);
74         } else {
75             A[i] = Complex(1, 0);
76             B[n-i-1] = Complex(0, 0);
77         }
78     }
79     for(int i = n; i < len; i++) {
80         A[i] = B[i] = Complex(0, 0);
81     }
82     fft(A, len, 1);
83     fft(B, len, 1);
84     for(int i = 0; i < len; i++) {
85         A[i] = A[i] * B[i];
86     }
87     fft(A, len, -1);
88     for(int i = n; i < n*2-1; i++) {
89         printf("%d
", (int)(A[i].x/len + 0.5));
90     }
91 }

Tourists

题意:给定一棵树,节点从1-n标号,对于节点i(1 <= 1 <= n),求出i到其倍数节点的距离总和

思路:利用LCA(倍增法),直接暴力即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn =200100;
 5 const int DEG = 30;
 6 
 7 struct Edge {
 8     int from, to, w;
 9 };
10 
11 vector<Edge> edges;
12 vector<int> G[maxn];
13 int g[maxn][DEG], gw[maxn][DEG];
14 int d[maxn];
15 int n, N;
16 
17 void addEdge(int u, int v, int w) {
18     edges.push_back({u, v, w});
19     edges.push_back({v, u, w});
20     G[u].push_back(edges.size() - 2);
21     G[v].push_back(edges.size() - 1);
22 }
23 
24 void init() {
25     N = floor(log(n+0.0) / log(2.0));
26     memset(g, 0, sizeof(g));
27     memset(gw, 0, sizeof(gw));
28     d[1] = 0;
29     for(int i = 0; i <= n; i++)
30         G[i].clear();
31     edges.clear();
32 }
33 
34 void dfs(int u) {
35     for(int i = 1; i <= N; i++) {
36         g[u][i] = g[g[u][i-1]][i-1];
37         gw[u][i] = gw[g[u][i-1]][i-1] + gw[u][i-1];
38     }
39     for(int i = 0; i < G[u].size(); i++) {
40         Edge e = edges[G[u][i]];
41         if(e.to != g[u][0]) {
42             d[e.to] = d[u] + 1;
43             gw[e.to][0] = e.w;
44             g[e.to][0] = u;
45             dfs(e.to);
46         }
47     }
48 }
49 
50 int lca(int a, int b) {
51     if(d[a] > d[b]) swap(a, b);
52     int ans = 0;
53     for(int i = N; i >= 0; i--) {
54         if(d[a] < d[b] && d[a] <= d[g[b][i]]) {
55             ans += gw[b][i];
56             b = g[b][i];
57         }
58     }
59     for(int i = N; i >= 0; i--) {
60         if(g[a][i] != g[b][i]) {
61             ans += gw[a][i];
62             ans += gw[b][i];
63             a = g[a][i];
64             b = g[b][i];
65         }
66     }
67     if(a != b) {
68         ans += gw[a][0];
69         ans += gw[b][0];
70     }
71     return ans;
72 }
73 
74 int main() {
75     int u, v;
76     scanf("%d", &n);
77     init();
78     for(int i = 1; i < n; i++) {
79         scanf("%d%d", &u, &v);
80         addEdge(u, v, 1);
81     }
82     dfs(1);
83     long long sum = 0;
84     for(int i=1; i<= n/2+1; i++) {
85         for(int j = i+i; j <= n; j += i)
86             sum += lca(i, j) + 1;
87     }
88     printf("%lld", sum);
89 }

 

以上是关于NAIPC 2016 K-Inversions I-Tourists的主要内容,如果未能解决你的问题,请参考以下文章

NAIPC2018 Pre?x Free Code(字典树)

线段树+扫描线 NAIPC 2019 Intersecting Rectangles

EXAM-2018-08-26

国庆补提二

The North American Invitational Programming Contest 2017 题目

[HEOI2016/TJOI2016]求和