码迷,mamicode.com
首页 > 其他好文 > 详细

2018.3.10 省选模拟赛

时间:2018-03-10 15:49:33      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:cas   gre   com   nbsp   sed   define   size   增加   邻接   

概况

  这是省选T1合集?还是欢乐AK赛?

  全班一半以上的人三道题都会做qwq。

  Doggu还剩一小时时以为自己AK了,然后玩了一小时。虽然最终被卡了20分的常数。

  ZJC 1个半小时AK?Excuse me?

  我这条大咸鱼到最后10分钟才敲完了T1,然后发现线段树要T掉。

  发自内心鄙视垃圾出题人卡常数,本来的欢乐AK变成280。

  教练给我们考4个小时的试,题面上也这么写的,看题解,woc,考试时间3小时。我觉得我做了假题。难道是noip模拟题?

Problem A 三元组

技术分享图片

  (题意过于简洁,不需要大意)

  暴力做法是枚举$a, b, c$中的中的一个,然后计算剩下两个中合法的对数(这个可以预处理)。

  于是我到了一个分治FFT的做法,时间复杂度$O(Tn log^{2}n)$,会被卡掉。

  但是这么做不优秀,没有利用题目的性质。

  对于$a$,恰好是1 ~ n。所以可以考虑从小到大枚举$c$,每次会增加1个可用的$a$和$b$。然后会对凑出和为$b + 1, b + 2, b + 3, \cdots$的地方有1的贡献。

  这是一个区间加的操作,用线段树树状数组就好了。

Code

技术分享图片
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #ifndef WIN32
 6 #define Auto "%lld"
 7 #else
 8 #define Auto "%I64d"
 9 #endif
10 using namespace std;
11 typedef bool boolean;
12 
13 #define ll long long
14 
15 typedef class IndexedTree {
16     public:
17         int k;
18         ll s[100005];
19         
20         IndexedTree() {        }
21         IndexedTree(int k):k(k) {
22             memset(s, 0, sizeof(ll) * (k + 1));
23         }
24         
25         void add(int idx, int x) {
26             idx++;
27             for ( ; idx <= k; idx += (idx & (-idx)))
28                 s[idx] += x;
29         }
30         
31         ll query(int idx) {
32             idx++;
33             ll rt = 0;
34             for ( ; idx; idx -= (idx & (-idx)))
35                 rt += s[idx];
36             return rt;    
37         }
38 
39         void add(int l, int r, int x) {
40             add(l, x);
41             add(r + 1, -x);
42         }
43         void modify(int x, int p) {
44             if (p >= k) {
45                 add(0, p / k);
46                 p %= k;
47             }
48             if (p < k && p) {
49                 if (x + p < k)
50                     add(x + 1, x + p, 1);
51                 else {
52                     if (x < k - 1) 
53                         add(x + 1, k - 1, 1);
54                     add(0, x + p - k, 1);
55                 }
56                 return;
57             }
58         }
59 }IndexedTree;
60 
61 const int N = 1e5 + 5;
62 
63 int n, k;
64 
65 inline void init() {
66     scanf("%d%d", &n, &k);
67 }
68 
69 ll ans = 0;
70 IndexedTree st;
71 inline void solve() {
72     ans = 0, st = IndexedTree(k);
73     for (int i = 1, b, c; i <= n; i++) {
74         b = i * 1ll * i % k, c = b * 1ll * i % k;
75         st.modify(b, i);
76         ans += st.query(c);
77     }
78     printf(Auto"\n", ans);
79 }
80 
81 int T;
82 int main() {
83     freopen("exclaim.in", "r", stdin);
84     freopen("exclaim.out", "w", stdout); 
85     scanf("%d", &T);
86     for (int kase = 1; kase <= T; kase++){
87         init();
88         printf("Case %d: ", kase);
89         solve();
90     }
91     return 0;
92 }
Problem A

Problem B 攻略

技术分享图片

  (题意极其简洁,不需要大意)

   去年省选D1T1。直接长链剖分。

Code

技术分享图片
  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #ifndef WIN32
  6 #define Auto "%lld"
  7 #else
  8 #define Auto "%I64d"
  9 #endif
 10 using namespace std;
 11 typedef bool boolean;
 12 
 13 #define ll long long
 14 
 15 typedef class Edge {
 16     public:
 17         int ed, nx;
 18 
 19         Edge(int ed = 0, int nx = 0):ed(ed), nx(nx) {    }
 20 }Edge;
 21 
 22 typedef class MapManager {
 23     public:
 24         int ce;
 25         int* h;
 26         Edge* es;
 27 
 28         MapManager() {    }
 29         MapManager(int n, int m):ce(0) {
 30             h = new int[(n + 1)];
 31             es = new Edge[(m + 1)];
 32             memset(h, 0, sizeof(int) * (n + 1));
 33         }
 34 
 35         void addEdge(int u, int v) {
 36             es[++ce] = Edge(v, h[u]);
 37             h[u] = ce;
 38         }
 39 
 40         Edge& operator [] (int pos) {
 41             return es[pos];
 42         }
 43 }MapManager;
 44 
 45 int n, k;
 46 MapManager g;
 47 int* vs;
 48 int *lson;
 49 ll res = 0;
 50 int top = 0;
 51 ll* secs;
 52 
 53 inline void init() {
 54     scanf("%d%d", &n, &k);
 55     vs = new int[(n + 1)];
 56     lson = new int[(n + 1)];
 57     secs = new ll[(n + 1)];
 58     g = MapManager(n, n << 1);
 59     for (int i = 1; i <= n; i++)
 60         scanf("%d", vs + i);
 61     for (int i = 1, u, v; i < n; i++) {
 62         scanf("%d%d", &u, &v);
 63         g.addEdge(u, v);
 64     }
 65 }
 66 
 67 ll dfs1(int p) {
 68     ll mxl = 0, mxs = 0, cmp;
 69     for (int i = g.h[p]; i; i = g[i].nx) {
 70         int e = g[i].ed;
 71         cmp = dfs1(e);
 72         if (cmp > mxl)
 73             mxl = cmp, mxs = e;
 74     }
 75     lson[p] = mxs;
 76     return mxl + vs[p];
 77 }
 78 
 79 void dfs2(int p, ll va) {
 80     boolean aflag = true;
 81     va += vs[p];
 82     if (lson[p])    aflag = false, dfs2(lson[p], va);
 83     for (int i = g.h[p]; i; i = g[i].nx, aflag = false) {
 84         int e = g[i].ed;
 85         if (e == lson[p])    continue;
 86         dfs2(e, 0);
 87     }
 88     if (aflag)
 89         secs[++top] = va;
 90 }
 91 
 92 inline void solve() {
 93     dfs1(1);
 94     dfs2(1, 0);
 95     sort(secs + 1, secs + top + 1, greater<ll>());
 96     for (int i = 1; i <= top && i <= k; i++)
 97         res += secs[i];
 98     printf(Auto"\n", res);
 99 }
100 
101 int main() {
102     freopen("game.in", "r", stdin);
103     freopen("game.out", "w", stdout);
104     init();
105     solve();
106     return 0;
107 }
Problem B

Problem C 迂回

技术分享图片

  (题意极度简洁,不需要大意)

  设原图的邻接矩阵为$A$,那么相当于求$A^{1} + A^{2} + \cdots + A^{k - 1}$的对角线上的和。

  直接用poj 3233的分治做法。

  但是这样$O(n^{3}\log^{2}k)$会T掉。

  考虑到分治中的快速幂很重复,其实可以把快速幂的过程和分治过程合并。

  时间复杂度$O(n^{3}\log k)$

Code

技术分享图片
 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef bool boolean;
 5 
 6 const int N = 105;
 7 
 8 typedef class Matrix {
 9     public:
10         int a[N][N];
11         
12         Matrix() {    }
13         Matrix(int n) {
14             for (int i = 0; i < n; i++)
15                 for (int j = 0; j < n; j++)
16                     a[i][j] = ((i == j) ? (1) : (0));
17         }
18 
19         int* operator [] (int p) {
20             return a[p];
21         }
22 }Matrix;
23 
24 int n, k, p;
25 char buf[233];
26 Matrix g;
27 
28 Matrix operator * (Matrix a, Matrix b) {
29     Matrix rt;
30     for (int i = 0; i < n; i++) {
31         for (int j = 0; j < n; j++) {
32             rt[i][j] = 0;
33             for (int k = 0; k < n; k++)
34                 rt[i][j] = (rt[i][j] + a[i][k] * 1ll * b[k][j]) % p;
35         }
36     }
37     return rt;
38 }
39 
40 Matrix operator + (Matrix a, Matrix b) {
41     Matrix rt;
42     for (int i = 0; i < n; i++) {
43         for (int j = 0; j < n; j++) {
44             rt[i][j] = (a[i][j] + b[i][j]) % p;
45         }
46     }
47     return rt;
48 }
49 
50 Matrix qpow(Matrix a, int pos) {
51     Matrix pa = a, rt = Matrix(n);
52     for ( ; pos; pos >>= 1, pa = pa * pa)
53         if (pos & 1)
54             rt = rt * pa;
55     return rt;
56 }
57 
58 inline void init() {
59     scanf("%d", &n);
60     for (int i = 0; i < n; i++) {
61         scanf("%s", buf);
62         for (int j = 0; j < n; j++)
63             g[i][j] = ((buf[j] == Y) ? (1) : (0));
64     }
65     scanf("%d%d", &k, &p);
66 }
67 
68 Matrix pa;
69 Matrix dividing(Matrix& a, int pos) {
70     if (pos == 1)
71         return (pa = a);
72     if (pos & 1) {
73         Matrix rt = dividing(a, pos - 1);
74         pa = pa * a; 
75         return rt + pa;
76     }
77     Matrix tem = dividing(a, pos >> 1), bas = pa;
78     for (int i = 0; i < n; i++)
79         bas[i][i] += 1;
80     pa = pa * pa;
81     return bas * tem;
82 }
83 
84 int res = 0;
85 inline void solve() {
86     Matrix a = dividing(g, k - 1);
87     for (int i = 0; i < n; i++)
88         res = (res + a[i][i]) % p;
89     printf("%d", res);
90 }
91 
92 int main() {
93     freopen("tour.in", "r", stdin);
94     freopen("tour.out", "w", stdout);
95     init();
96     solve();
97     return 0;
98 }
Problem C

2018.3.10 省选模拟赛

标签:cas   gre   com   nbsp   sed   define   size   增加   邻接   

原文地址:https://www.cnblogs.com/yyf0309/p/8538903.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!