zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Android OpenGL ES 2.0 (四) 灯光perfragment lighting
    Android OpenGL ES 2.0 (五) 添加材质
    冒泡排序函数
    javascript object 转换为 json格式 toJSONString
    Liunx CentOS 下载地址
    jquery 图片切换特效 鼠标点击左右按钮焦点图切换滚动
    javascript 解析csv 的function
    mysql Innodb Shutdown completed; log sequence number解决办法
    Centos 添加 yum
    javascript 键值转换
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4587027.html
Copyright © 2011-2022 走看看