• 4105: [Thu Summer Camp 2015]平方运算


    首先嘛这道题目只要知道一个东西就很容易了:所有循环的最小公约数<=60,成一条链的长度最大为11,那么我们就可以用一个很裸的方法。对于在链上的数,我们修改直接暴力找出并修改。对于在环上的数,我们对每一步建立一颗线段树,那么修改就变成了交换60棵线段树的某个子树。然后我们就可以愉快的写啦~~~

    在想的时候被同学坑了,他说最长的循环不超过60.。。。

    在实现方面,我用一个map+树状数组维护链上的答案,然后用60棵线段树来维护这个环。懂了之后还是很好写哒~~~

    Code:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4  
      5 const int N = 100000 + 10, kCycle = 60 + 10;
      6  
      7 int n, m, p, x[N];
      8  
      9 int dist[N], cycle = 1;
     10  
     11 inline int GCD(int a, int b) { return b ? GCD(b, a % b) : a; }
     12 inline int LCM(int a, int b) { return a * b / GCD(a, b); }
     13  
     14 int pre[N];
     15  
     16 void Analysis(int a) {
     17   dist[a] = -2;
     18   int b = a * a % p;
     19   if (dist[b] == -1) {
     20     pre[b] = a;
     21     Analysis(b);
     22   } else if (dist[b] == -2) {
     23     int cnt = 1;
     24     for (int i = a; i != b; i = pre[i], ++cnt) dist[i] = 0;
     25     dist[b] = 0;
     26     cycle = LCM(cycle, cnt);
     27   }
     28   if (dist[a] == -2) dist[a] = dist[b] + 1;
     29 }
     30  
     31 inline int pos(int l, int r) { return (l + r) | (l != r); }
     32  
     33 int tree[N * 2][kCycle], shift[N * 2]; 
     34  
     35 inline void Merge(int u[], int a[], int b[]) {
     36   for (int i = 0; i < cycle; ++i) u[i] = a[i] + b[i];
     37 }
     38  
     39 inline void Shift(int id, int v) {
     40   static int temp[kCycle * 2];
     41   (shift[id] += v) %= cycle;
     42   for (int i = 0; i < cycle; ++i) temp[i] = tree[id][(i + v) % cycle];  
     43   std::copy(temp, temp + cycle, tree[id]);
     44 }
     45  
     46 void Modify(int l, int r, int u, int v) {
     47   int id = pos(l, r);
     48   for (int i = 0; i < cycle; ++i, (v *= v) %= p) tree[id][i] += v;
     49   if (l == r) return;
     50   int mid = (l + r) / 2;
     51   if (shift[id]) {
     52     Shift(pos(l, mid), shift[id]);
     53     Shift(pos(mid + 1, r), shift[id]);
     54     shift[id] = 0;
     55   }
     56   if (u <= mid) Modify(l, mid, u, v); else Modify(mid + 1, r, u, v);
     57 }
     58  
     59 void Cycle(int l, int r, int u, int v) {
     60   int id = pos(l, r);
     61   if (u <= l && r <= v) {
     62     Shift(id, 1);
     63     return;
     64   }
     65   int mid = (l + r) / 2;
     66   if (shift[id]) {
     67     Shift(pos(l, mid), shift[id]);
     68     Shift(pos(mid + 1, r), shift[id]);
     69     shift[id] = 0;
     70   }
     71   if (u <= mid) Cycle(l, mid, u, v);
     72   if (v > mid) Cycle(mid + 1, r, u, v);
     73   Merge(tree[id], tree[pos(l, mid)], tree[pos(mid + 1, r)]);
     74 }
     75  
     76 int Query(int l, int r, int u, int v) {
     77   int id = pos(l, r);
     78   if (u <= l && r <= v) return tree[id][0];
     79   int mid = (l + r) / 2, res = 0;
     80   if (shift[id]) {
     81     Shift(pos(l, mid), shift[id]);
     82     Shift(pos(mid + 1, r), shift[id]);
     83     shift[id] = 0;
     84   }
     85   if (u <= mid) res += Query(l, mid, u, v);
     86   if (v > mid) res += Query(mid + 1, r, u, v);
     87   return res;
     88 }
     89  
     90 class BIT {
     91   int data[N];
     92  
     93  public:
     94   inline void Add(int p, int v) { for (; p <= n; p += p & -p) data[p] += v; } 
     95   inline int Query(int p) {
     96     int res = 0;
     97     for (; p; p ^= p & -p) res += data[p];
     98     return res;
     99   }
    100   inline int Query(int l, int r) { return Query(r) - Query(l - 1); }
    101  
    102 } cnt, sum;
    103  
    104 void Sqr(int l, int r) {
    105   if (!cnt.Query(l, r)) return;
    106   if (l == r) {
    107     cnt.Add(l, -1);
    108     sum.Add(l, -x[l]);
    109     if (cnt.Query(l, l) == 0)
    110       Modify(1, n, l, (x[l] *= x[l]) %= p);
    111     else
    112       sum.Add(l, (x[l] *= x[l]) %= p);
    113   } else {
    114     int mid = (l + r) / 2;
    115     Sqr(l, mid);
    116     Sqr(mid + 1, r);
    117   }
    118 }
    119  
    120 int main() {
    121   scanf("%d%d%d", &n, &m, &p);
    122   for (int i = 1; i <= n; ++i) scanf("%d", x + i);
    123   memset(dist, -1, sizeof dist);
    124   for (int i = 0; i < p; ++i) if (dist[i] == -1) Analysis(i);
    125   for (int i = 1; i <= n; ++i) {
    126     if (dist[x[i]]) {
    127       sum.Add(i, x[i]);
    128       cnt.Add(i, dist[x[i]]);
    129     } else {
    130       Modify(1, n, i, x[i]);
    131     }
    132   }
    133   while (m--) {
    134     int op, l, r;
    135     scanf("%d%d%d", &op, &l, &r);
    136     switch (op) {
    137       case 0:
    138         Cycle(1, n, l, r);
    139         Sqr(l, r);
    140         break;
    141       case 1:
    142         printf("%d
    ", Query(1, n, l, r) + sum.Query(l, r));
    143         break;
    144     }
    145   }
    146   return 0;
    147 }
  • 相关阅读:
    TomCat 的 Jenkins 报错:反向代理设置有误
    【Django】如何在类视图、普通视图单独不做CSRF校验
    【Django】HTML如何显示富文本内容
    Djaong 运行报错:ValueError: Unable to configure handler 'default'
    Windows 环境使用 Xshell 连接 VMware 虚拟机上的 CentOS 系统
    【我的青春我做主】让自己的心境安宁
    Django 使用 Nginx + uWSGI 启动
    Django_文件下载
    追梦何须要问成败,只管向前吧
    PyCharm:设置py文件头部信息
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4587027.html
Copyright © 2020-2023  润新知