[关闭]
@Pinetrie 2019-08-25T14:48:19.000000Z 字数 17882 阅读 866

模板

数位dp

l到r的数字中没有4和62的数有多少个

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int n,m,dp[20][2],num[20];
  4. int dfs(int pos,int if6,int limit)
  5. {
  6. if(pos == 0) return 1;
  7. if(!limit && dp[pos][if6] != -1) return dp[pos][if6];
  8. int up = limit ? num[pos] : 9;
  9. int temp = 0;
  10. for(int i = 0;i <= up;i++)
  11. {
  12. if(i == 4) continue;
  13. if(if6 == 1 && i == 2) continue;
  14. temp += dfs(pos - 1,i == 6,limit && i == num[pos]);
  15. }
  16. if(!limit) dp[pos][if6] = temp;
  17. return temp;
  18. }
  19. int solve(int x)
  20. {
  21. int tot = 0;
  22. while(x)
  23. {
  24. num[++tot] = x % 10;
  25. x /= 10;
  26. }
  27. return dfs(tot,0,1);
  28. }
  29. int main()
  30. {
  31. while(scanf("%d %d",&n,&m) && (n + m))
  32. {
  33. memset(dp,-1,sizeof(dp));
  34. printf("%d\n",solve(m) - solve(n - 1));
  35. }
  36. return 0;
  37. }

二分图最大匹配算法

求最小顶点覆盖集的方法:

如果是拿匈牙利跑的话,需要求出最大匹配后,从左部的每个非匹配点再跑dfs,最终左边未被标记的点,与右边被标记的点就是覆盖的点集。如果是拿dinic分层跑的话,左部的点就是d[]为0的点,右部就是d[]不为0的点。

  1. #include <bits/stdc++.h>
  2. #define MAX_V 1100
  3. using namespace std;
  4. int V,P;
  5. vector<int> G[MAX_V];
  6. int match[MAX_V];
  7. bool used[MAX_V];
  8. void add_edge(int u,int v)
  9. {
  10. G[u].push_back(v);
  11. G[v].push_back(u);
  12. }
  13. bool dfs(int v)
  14. {
  15. used[v] = true;
  16. for(int i = 0;i < (int)G[v].size();i++)
  17. {
  18. int u = G[v][i];
  19. if(!used[u])
  20. {
  21. used[u] = 1;
  22. if(match[u] == -1 || dfs(match[u]))
  23. {
  24. match[u] = v;
  25. match[v] = u;
  26. return 1;
  27. }
  28. }
  29. }
  30. return false;
  31. }
  32. int binary_match()
  33. {
  34. int res = 0;
  35. memset(match,-1,sizeof(match));
  36. for(int v = 0; v < V; v++)
  37. {
  38. if(match[v] < 0)
  39. {
  40. memset(used,0,sizeof(used));
  41. if(dfs(v))
  42. {
  43. res++;
  44. }
  45. }
  46. }
  47. return res;
  48. }
  49. int main()
  50. {
  51. int T;
  52. scanf("%d",&T);
  53. while(T--)
  54. {
  55. for(int i = 1;i <= MAX_V;i++) G[i].clear();
  56. scanf("%d %d",&P,&V);
  57. V += P;
  58. for(int i = 1;i <= P;i++)
  59. {
  60. int n;
  61. scanf("%d",&n);
  62. for(int j = 1;j <= n;j++)
  63. {
  64. int x;
  65. scanf("%d",&x);
  66. add_edge(i,x + P);
  67. }
  68. }
  69. int edge_num = binary_match();
  70. if(edge_num == P) printf("YES\n");
  71. else printf("NO\n");
  72. }
  73. return 0;
  74. }

高斯消元

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const double EPS = 1E-8;
  4. typedef vector<double> vec;
  5. typedef vector<vec> mat;
  6. //求解Ax = b,其中A是方阵//
  7. //当方程无解或无穷多解时,返回一个长度为0的数组//
  8. vec gauss_jordan(const mat& A,const vec& b)
  9. {
  10. int n = A.size();
  11. mat B(n,vec(n + 1));
  12. for(int i = 0; i < n; i++)
  13. for(int j = 0; j < n; j++)
  14. B[i][j] = A[i][j];
  15. //把b存放在A的右边方便一起处理//
  16. for(int i = 0; i < n; i++)
  17. B[i][n] = b[i];
  18. for(int i = 0; i < n; i++)
  19. {
  20. //把正在处理的未知数系数最大的式子换到第i行//
  21. int pivot = i;
  22. for(int j = i; j < n; j++)
  23. {
  24. if(abs(B[j][i] > abs(B[pivot][i])))
  25. pivot = j;
  26. }
  27. swap(B[i],B[pivot]);
  28. //无解或者无穷多解//
  29. if(abs(B[i][i]) < EPS)
  30. return vec();
  31. //把正在处理的未知数系数边为1//
  32. for(int j = i + 1; j <= n; j++)
  33. B[i][j] /= B[i][i];
  34. for(int j = 0; j < n; j++)
  35. {
  36. if(i != j)
  37. {
  38. //从第j个式子中消去第i个未知数//
  39. for(int k = i + 1; k <= n; k++)
  40. B[j][k] -= B[j][i] * B[i][k];
  41. }
  42. }
  43. }
  44. vec x(n);
  45. //存放在右边的b就是答案//
  46. for(int i = 0; i < n; i++)
  47. x[i] = B[i][n];
  48. return x;
  49. }
  50. int main()
  51. {
  52. int n;
  53. scanf("%d",&n);
  54. mat A(n,vec(n));
  55. vec B(n);
  56. for(int i = 0; i < n; i++)
  57. {
  58. for(int j = 0; j < n; j++)
  59. {
  60. double val;
  61. scanf("%lf",&val);
  62. A[i][j] = val;
  63. }
  64. }
  65. for(int i = 0; i < n; i++)
  66. {
  67. double val;
  68. scanf("%lf",&val);
  69. B[i] = val;
  70. }
  71. vec C = gauss_jordan(A,B);
  72. for(int i = 0; i < n; i++)
  73. printf("%f ",C[i]);
  74. return 0;
  75. }
  76. /*
  77. 输入:
  78. 3
  79. 1 -2 3
  80. 4 -5 6
  81. 7 -8 10
  82. 6 12 21
  83. 输出:
  84. 1.00000 2.00000 3.00000
  85. */

LCA targan离线

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 40010;
  4. int n,m,tot,qtot;
  5. int head[maxn * 2],qhead[maxn * 2],dis[maxn],vis[maxn],fa[maxn],LCA[maxn];
  6. struct NODE
  7. {
  8. int v,next,w;
  9. }node[maxn * 2];
  10. struct QNODE
  11. {
  12. int v,next,w;
  13. }qnode[maxn * 2];
  14. struct ASK
  15. {
  16. int x1,x2;
  17. }ask[maxn];
  18. void init()
  19. {
  20. memset(head,-1,sizeof(head));
  21. memset(qhead,-1,sizeof(qhead));
  22. memset(dis,0x3f3f3f3f,sizeof(dis));
  23. dis[1] = 0;
  24. memset(vis,0,sizeof(vis));
  25. for(int i = 1;i <= n;i++) fa[i] = i;
  26. tot = qtot = 0;
  27. }
  28. void addnode(int u,int v,int w)
  29. {
  30. node[tot].v = v;
  31. node[tot].w = w;
  32. node[tot].next = head[u];
  33. head[u] = tot++;
  34. }
  35. void addnodeq(int u,int v,int w)
  36. {
  37. qnode[qtot].v = v;
  38. qnode[qtot].w = w;
  39. qnode[qtot].next = qhead[u];
  40. qhead[u] = qtot++;
  41. }
  42. int Find(int x)
  43. {
  44. if(x == fa[x]) return x;
  45. return fa[x] = Find(fa[x]);
  46. }
  47. void tarjan(int u)
  48. {
  49. vis[u] = 1;
  50. for(int i = qhead[u];i != -1;i = qnode[i].next)
  51. {
  52. int v = qnode[i].v;
  53. if(vis[v]) LCA[qnode[i].w] = Find(fa[v]);
  54. }
  55. for(int i = head[u];i != -1;i = node[i].next)
  56. {
  57. int v = node[i].v,w = node[i].w;
  58. if(!vis[v])
  59. {
  60. dis[v] = dis[u] + w;
  61. tarjan(v);
  62. fa[v] = u;
  63. }
  64. }
  65. }
  66. int main()
  67. {
  68. int T;
  69. scanf("%d",&T);
  70. while(T--)
  71. {
  72. scanf("%d %d",&n,&m);
  73. init();
  74. //for(int i = 1;i <= n;i++) printf("%d\n",fa[i]);//
  75. for(int i = 1;i < n;i++)
  76. {
  77. int u,v,w;
  78. scanf("%d %d %d",&u,&v,&w);
  79. addnode(u,v,w);
  80. addnode(v,u,w);
  81. }
  82. for(int i = 1;i <= m;i++)
  83. {
  84. int u,v;
  85. scanf("%d %d",&u,&v);
  86. addnodeq(u,v,i);
  87. addnodeq(v,u,i);
  88. ask[i].x1 = u,ask[i].x2 = v;
  89. }
  90. tarjan(1);
  91. for(int i = 1;i <= m;i++)
  92. {
  93. int u = ask[i].x1,v = ask[i].x2;
  94. printf("%d\n",dis[u] + dis[v] - 2 * dis[LCA[i]]);
  95. }
  96. }
  97. return 0;
  98. }

高精度+,-,*,/,%

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <iostream>
  5. using namespace std;
  6. #define maxn 2000
  7. #define base 10000
  8. struct Bign
  9. {
  10. int c[maxn],len,sign;
  11. //初始化
  12. Bign(){memset(c,0,sizeof(c)),len = 1,sign = 0;}
  13. //高位清零
  14. void Zero()
  15. {
  16. while(len > 1 && c[len] == 0)len--;
  17. if(len == 1 && c[len] == 0)sign = 0;
  18. }
  19. //压位读入
  20. void Write(char *s)
  21. {
  22. int k = 1,l = strlen(s);
  23. for(int i = l - 1;i >= 0;i--)
  24. {
  25. c[len] += (s[i] - '0') * k;
  26. k *= 10;
  27. if(k == base)
  28. {
  29. k = 1;
  30. len++;
  31. }
  32. }
  33. }
  34. void Read()
  35. {
  36. char s[maxn] = {0};
  37. scanf("%s",s);
  38. Write(s);
  39. }
  40. //输出
  41. void Print()
  42. {
  43. if(sign)printf("-");
  44. printf("%d",c[len]);
  45. for(int i = len - 1;i >= 1;i--)printf("%04d",c[i]);
  46. printf("\n");
  47. }
  48. //重载 = 运算符,将低精赋值给高精
  49. Bign operator = (int a)
  50. {
  51. char s[100];
  52. sprintf(s,"%d",a);
  53. Write(s);
  54. return *this;//this只能用于成员函数,表示当前对象的地址
  55. }
  56. //重载 < 运算符
  57. bool operator < (const Bign &a)const
  58. {
  59. if(len != a.len)return len < a.len;
  60. for(int i = len;i >= 1;i--)
  61. {
  62. if(c[i] != a.c[i])return c[i] < a.c[i];
  63. }
  64. return 0;
  65. }
  66. bool operator > (const Bign &a)const
  67. {
  68. return a < *this;
  69. }
  70. bool operator <= (const Bign &a)const
  71. {
  72. return !(a < *this);
  73. }
  74. bool operator >= (const Bign &a)const
  75. {
  76. return !(*this < a);
  77. }
  78. bool operator != (const Bign &a)const
  79. {
  80. return a < *this || *this < a;
  81. }
  82. bool operator == (const Bign &a)const
  83. {
  84. return !(a < *this) && !(*this < a);
  85. }
  86. bool operator == (const int &a)const
  87. {
  88. Bign b;b = a;
  89. return *this == b;
  90. }
  91. //重载 + 运算符
  92. Bign operator + (const Bign &a)
  93. {
  94. Bign r;
  95. r.len = max(len,a.len) + 1;
  96. for(int i = 1;i <= r.len;i++)
  97. {
  98. r.c[i] += c[i] + a.c[i];
  99. r.c[i + 1] += r.c[i] / base;
  100. r.c[i] %= base;
  101. }
  102. r.Zero();
  103. return r;
  104. }
  105. Bign operator + (const int &a)
  106. {
  107. Bign b;b = a;
  108. return *this + b;
  109. }
  110. //重载 - 运算符
  111. Bign operator - (const Bign &a)
  112. {
  113. Bign b,c;// b - c
  114. b = *this;
  115. c = a;
  116. if(c > b)
  117. {
  118. swap(b,c);
  119. b.sign = 1;
  120. }
  121. for(int i = 1;i <= b.len;i++)
  122. {
  123. b.c[i] -= c.c[i];
  124. if(b.c[i] < 0)
  125. {
  126. b.c[i] += base;
  127. b.c[i + 1]--;
  128. }
  129. }
  130. b.Zero();
  131. return b;
  132. }
  133. Bign operator - (const int &a)
  134. {
  135. Bign b;b = a;
  136. return *this - b;
  137. }
  138. //重载 * 运算符
  139. Bign operator * (const Bign &a)
  140. {
  141. Bign r;
  142. r.len = len + a.len + 2;
  143. for(int i = 1;i <= len;i++)
  144. {
  145. for(int j = 1;j <= a.len;j++)
  146. {
  147. r.c[i + j - 1] += c[i] * a.c[j];
  148. }
  149. }
  150. for(int i = 1;i <= r.len;i++)
  151. {
  152. r.c[i + 1] += r.c[i] / base;
  153. r.c[i] %= base;
  154. }
  155. r.Zero();
  156. return r;
  157. }
  158. Bign operator * (const int &a)
  159. {
  160. Bign b;b = a;
  161. return *this * b;
  162. }
  163. //重载 / 运算符
  164. Bign operator / (const Bign &b)
  165. {
  166. Bign r,t,a;
  167. a = b;
  168. //if(a == 0)return r;
  169. r.len = len;
  170. for(int i = len;i >= 1;i--)
  171. {
  172. t = t * base + c[i];
  173. int div,ll = 0,rr = base;
  174. while(ll <= rr)
  175. {
  176. int mid = (ll + rr) / 2;
  177. Bign k = a * mid;
  178. if(k > t)rr = mid - 1;
  179. else
  180. {
  181. ll = mid + 1;
  182. div = mid;
  183. }
  184. }
  185. r.c[i] = div;
  186. t = t - a * div;
  187. }
  188. r.Zero();
  189. return r;
  190. }
  191. Bign operator / (const int &a)
  192. {
  193. Bign b;b = a;
  194. return *this / b;
  195. }
  196. //重载 % 运算符
  197. Bign operator % (const Bign &a)
  198. {
  199. return *this - *this / a * a;
  200. }
  201. Bign operator % (const int &a)
  202. {
  203. Bign b;b = a;
  204. return *this % b;
  205. }
  206. };
  207. int main()
  208. {
  209. Bign a,b,c,d,e,f,g;
  210. a.Read();
  211. b.Read();
  212. c = a + b;
  213. c.Print();
  214. d = a - b;
  215. d.Print();
  216. e = a * b;
  217. e.Print();
  218. f = a / b;
  219. f.Print();
  220. g = a % b;
  221. g.Print();
  222. return 0;
  223. }

exgcd

  1. #include<iostream>
  2. using namespace std;
  3. int exgcd(int a,int b,int &x,int &y)
  4. {
  5. if(b==0)
  6. {
  7. x=1;
  8. y=0;
  9. return a;
  10. }
  11. int gcd=exgcd(b,a%b,x,y);
  12. int x2=x,y2=y;
  13. x=y2;
  14. y=x2-(a/b)*y2;
  15. return gcd;
  16. }
  17. int main()
  18. {
  19. int x,y,a,b;
  20. cout<<"请输入a和b:"<<endl;
  21. cin>>a>>b;
  22. cout<<"a和b的最大公约数:"<<endl;
  23. cout<<exgcd(a,b,x,y)<<endl;
  24. cout<<"ax+by=gcd(a,b) 的一组解是:"<<endl;
  25. cout<<x<<" "<<y<<endl;
  26. return 0;
  27. }

manacher

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 100010;
  4. char s[maxn],temp[2 * maxn];
  5. int p[2 * maxn];
  6. void init() {
  7. int n = strlen(s);
  8. temp[0] = '$';
  9. for(int i = 1;i <= n;i++) {
  10. temp[i * 2] = s[i - 1];
  11. temp[i * 2 - 1] = '#';
  12. }
  13. temp[n * 2 + 1] = '#';
  14. temp[n * 2 + 2] = '\0';
  15. }
  16. int manacher() {
  17. int n = 2 * strlen(s) + 1;
  18. int mx = 0,ans = 0,mark = 0;
  19. for(int i = 1;i <= n;i++) {
  20. if(mx > i) p[i] = min(mx - i,p[mark * 2 - i]);
  21. else p[i] = 1;
  22. while(temp[i + p[i]] == temp[i - p[i]]) p[i]++;
  23. if(i + p[i] > mx) {
  24. mx = p[i] + i;
  25. mark = i;
  26. }
  27. ans = max(ans,p[i]);
  28. }
  29. return ans - 1;
  30. }
  31. int main() {
  32. while(scanf("%s",s) != EOF) {
  33. init();
  34. printf("%d\n",manacher());
  35. }
  36. return 0;
  37. }

RMQ

快速查询区间最值

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. const int maxn = 100010;
  5. int Min[maxn][20],Max[maxn][20],a[maxn];
  6. int n,q;
  7. struct RMQ
  8. {
  9. int log2[maxn];
  10. void init()
  11. {
  12. for(int i = 0;i <= n;i++) log2[i] = (i == 0 ? -1 : log2[i>>1] + 1);
  13. for(int j = 1;j < 20;j++)
  14. {
  15. for(int i = 1;i + (1<<j) <= n + 1;i++)
  16. {
  17. Min[i][j] = min(Min[i][j - 1],Min[i + (1<<(j - 1))][j - 1]);
  18. Max[i][j] = max(Max[i][j - 1],Max[i + (1<<(j - 1))][j - 1]);
  19. }
  20. }
  21. }
  22. int Min_query(int l,int r)
  23. {
  24. int k = log2[r - l + 1];
  25. return min(Min[l][k],Min[r - (1<<k) + 1][k]);
  26. }
  27. int Max_query(int l,int r)
  28. {
  29. int k = log2[r - l + 1];
  30. return max(Max[l][k],Max[r - (1<<k) + 1][k]);
  31. }
  32. };
  33. int main()
  34. {
  35. scanf("%d %d",&n,&q);
  36. for(int i = 1;i <= n;i++)
  37. {
  38. scanf("%d",&a[i]);
  39. Min[i][0] = a[i];
  40. Max[i][0] = a[i];
  41. }
  42. RMQ rmq;
  43. rmq.init();
  44. for(int i = 1;i <= q;i++)
  45. {
  46. int l,r;
  47. scanf("%d %d",&l,&r);
  48. printf("%d\n",rmq.Max_query(l,r) - rmq.Min_query(l,r));
  49. }
  50. return 0;
  51. }

莫队算法

离线解决区间询问
q*sqrt(n)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn = 500100;
  5. struct Que
  6. {
  7. ll l,r,id,block;
  8. Que() {}
  9. Que(ll l,ll r,ll id):l(l),r(r),id(id) {}
  10. bool operator < (const Que &rhs) const
  11. {
  12. if(block == rhs.block) return r < rhs.r;
  13. return block < rhs.block;
  14. }
  15. }ques[maxn];
  16. ll n,m,len;
  17. ll a[maxn];
  18. ll ansx[maxn],ansy[maxn],sum;
  19. ll cor[maxn];
  20. void add(ll x)
  21. {
  22. sum += 2 * cor[x];
  23. cor[x]++;
  24. }
  25. void sub(ll x)
  26. {
  27. sum -= (2 * cor[x] - 2);
  28. cor[x]--;
  29. }
  30. ll gcd(ll x,ll y)
  31. {
  32. return y == 0 ? x : gcd(y,x % y);
  33. }
  34. int main()
  35. {
  36. scanf("%lld %lld",&n,&m);
  37. len = sqrt(n);
  38. for(int i = 1;i <= n;i++) scanf("%lld",&a[i]);
  39. for(int i = 1;i <= m;i++)
  40. {
  41. ll l,r;
  42. scanf("%lld %lld",&l,&r);
  43. ques[i] = Que(l,r,i);
  44. ques[i].block = l / len;
  45. }
  46. sort(ques + 1,ques + 1 + m);
  47. ll L = 1,R = 1;
  48. cor[a[1]]++;
  49. sum = 0;
  50. for(int i = 1;i <= m;i++)
  51. {
  52. ll l = ques[i].l,r = ques[i].r,id = ques[i].id;
  53. while(R < r) add(a[++R]);
  54. while(L > l) add(a[--L]);
  55. while(R > r) sub(a[R--]);
  56. while(L < l) sub(a[L++]);
  57. ll cnt1 = sum;
  58. ll cnt2 = (ll)(r - l + 1) * (r - l);
  59. if(cnt1 == 0)
  60. {
  61. ansx[id] = 0,ansy[id] = 1;
  62. continue;
  63. }
  64. ll k = gcd(cnt1,cnt2);
  65. ansx[id] = cnt1 / k,ansy[id] = cnt2 / k;
  66. }
  67. for(int i = 1;i <= m;i++)
  68. {
  69. printf("%lld/%lld\n",ansx[i],ansy[i]);
  70. }
  71. return 0;
  72. }

树链剖分

题目描述
如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:
操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z
操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和
操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z
操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

输入格式:
第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。
接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。
接下来N-1行每行包含两个整数x、y,表示点x和点y之间连有一条边(保证无环且连通)
接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:
操作1: 1 x y z
操作2: 2 x y
操作3: 3 x z
操作4: 4 x

输出格式:
输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn = 100010;
  5. ll w[maxn],root;
  6. ll N,M,R,P;
  7. //线段树///////////////////////////////////////////////////////////////////
  8. ll A[maxn<<2],Sum[maxn<<2],Add[maxn<<2];
  9. void Pushup(ll rt)
  10. {
  11. Sum[rt] = (Sum[rt<<1] + Sum[rt<<1|1]) % P;
  12. }
  13. void Pushdown(ll rt,ll ln,ll rn)
  14. {
  15. if(Add[rt])
  16. {
  17. Add[rt<<1] = (Add[rt<<1] + Add[rt]) % P;
  18. Add[rt<<1|1] = (Add[rt<<1|1] + Add[rt]) % P;
  19. Sum[rt<<1] = (Sum[rt<<1] + ln * Add[rt]) % P;
  20. Sum[rt<<1|1] = (Sum[rt<<1|1] + rn * Add[rt]) % P;
  21. Add[rt] = 0;
  22. }
  23. }
  24. void build(ll l,ll r,ll rt)
  25. {
  26. if(l == r)
  27. {
  28. Sum[rt] = A[l];
  29. return;
  30. }
  31. ll m = (l + r)>>1;
  32. build(l,m,rt<<1);
  33. build(m + 1,r,rt<<1|1);
  34. Pushup(rt);
  35. }
  36. ll query(ll L,ll R,ll l,ll r,ll rt)
  37. {
  38. if(L <= l && R >= r)
  39. {
  40. return Sum[rt];
  41. }
  42. ll m = (l + r)>>1;
  43. Pushdown(rt,m - l + 1,r - m);
  44. ll Ans = 0;
  45. if(L <= m) Ans = (Ans + query(L,R,l,m,rt<<1)) % P;
  46. if(R > m) Ans = (Ans + query(L,R,m + 1,r,rt<<1|1)) % P;
  47. return Ans;
  48. }
  49. void update(ll L,ll R,ll C,ll l,ll r,ll rt)
  50. {
  51. if(L <= l && R >= r)
  52. {
  53. Sum[rt] = (Sum[rt] + (r - l + 1) * C) % P;
  54. Add[rt] = (Add[rt] + C) % P;
  55. return;
  56. }
  57. ll m = (l + r)>>1;
  58. Pushdown(rt,m - l + 1,r - m);
  59. if(L <= m) update(L,R,C,l,m,rt<<1);
  60. if(R > m) update(L,R,C,m + 1,r,rt<<1|1);
  61. Pushup(rt);
  62. }
  63. //////////////////////////////////////////////////////////
  64. 预处理///////////////////////////////////////////////////
  65. ll head[maxn],f[maxn],dep[maxn],siz[maxn],son[maxn],rk[maxn],top[maxn],id[maxn];
  66. ll tot,cnt;
  67. struct Edge
  68. {
  69. ll v,next;
  70. }e[maxn * 2];
  71. void addnode(ll u,ll v)
  72. {
  73. e[tot].v = v;
  74. e[tot].next = head[u];
  75. head[u] = tot++;
  76. }
  77. void dfs1(ll u,ll fa,ll deep)
  78. {
  79. f[u] = fa;
  80. dep[u] = deep;
  81. siz[u] = 1;
  82. for(ll i = head[u];i != -1;i = e[i].next)
  83. {
  84. ll v = e[i].v;
  85. if(v == fa) continue;
  86. dfs1(v,u,deep + 1);
  87. siz[u] += siz[v];
  88. if(siz[v] > siz[son[u]]) son[u] = v;
  89. }
  90. }
  91. void dfs2(ll u,ll t)
  92. {
  93. top[u] = t;
  94. id[u] = ++cnt;
  95. rk[cnt] = u;
  96. if(!son[u]) return;
  97. dfs2(son[u],t);
  98. for(ll i = head[u];i != -1;i = e[i].next)
  99. {
  100. ll v = e[i].v;
  101. if(v != son[u] && v != f[u]) dfs2(v,v);
  102. }
  103. }
  104. 询问//////////////////////////////////////////
  105. ll getsum(ll x,ll y)
  106. {
  107. ll ans = 0,fx = top[x],fy = top[y];
  108. while(fx != fy)
  109. {
  110. if(dep[fx] >= dep[fy])
  111. {
  112. ans = (ans + query(id[fx],id[x],1,N,1)) % P;
  113. x = f[fx],fx = top[x];
  114. }
  115. else
  116. {
  117. ans = (ans + query(id[fy],id[y],1,N,1)) % P;
  118. y = f[fy],fy = top[y];
  119. }
  120. }
  121. if(id[x] <= id[y]) ans = (ans + query(id[x],id[y],1,N,1)) % P;
  122. else ans = (ans + query(id[y],id[x],1,N,1)) % P;
  123. return ans;
  124. }
  125. void getupdate(ll x,ll y,ll C)
  126. {
  127. ll fx = top[x],fy = top[y];
  128. while(fx != fy)
  129. {
  130. if(dep[fx] >= dep[fy])
  131. {
  132. update(id[fx],id[x],C,1,N,1);
  133. x = f[fx],fx = top[x];
  134. }
  135. else
  136. {
  137. update(id[fy],id[y],C,1,N,1);
  138. y = f[fy],fy = top[y];
  139. }
  140. }
  141. if(id[x] <= id[y]) update(id[x],id[y],C,1,N,1);
  142. else update(id[y],id[x],C,1,N,1);
  143. }
  144. ll getsonsum(ll x)
  145. {
  146. return query(id[x],id[x] + siz[x] - 1,1,N,1);
  147. }
  148. void getsonupdate(ll x,ll z)
  149. {
  150. update(id[x],id[x] + siz[x] - 1,z,1,N,1);
  151. }
  152. int main()
  153. {
  154. memset(head,-1,sizeof(head));
  155. scanf("%lld %lld %lld %lld",&N,&M,&R,&P);
  156. for(ll i = 1;i <= N;i++) scanf("%lld",&w[i]);
  157. for(ll i = 1;i < N;i++)
  158. {
  159. ll u,v;
  160. scanf("%lld %lld",&u,&v);
  161. addnode(u,v);
  162. addnode(v,u);
  163. }
  164. dfs1(R,0,1);
  165. dfs2(R,R);
  166. for(ll i = 1;i <= N;i++)
  167. {
  168. A[i] = w[rk[i]];
  169. }
  170. build(1,N,1);
  171. while(M--)
  172. {
  173. ll op,x,y,z;
  174. scanf("%lld",&op);
  175. if(op == 1)
  176. {
  177. scanf("%lld %lld %lld",&x,&y,&z);
  178. getupdate(x,y,z);
  179. }
  180. if(op == 2)
  181. {
  182. scanf("%lld %lld",&x,&y);
  183. printf("%lld\n",getsum(x,y));
  184. }
  185. if(op == 3)
  186. {
  187. scanf("%lld %lld",&x,&z);
  188. getsonupdate(x,z);
  189. }
  190. if(op == 4)
  191. {
  192. scanf("%lld",&x);
  193. printf("%lld\n",getsonsum(x));
  194. }
  195. }
  196. return 0;
  197. }

主席树(区间第K大)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 100010;
  4. int T,n,m,np;
  5. int L[maxn*20],R[maxn*20],Sum[maxn*20],A[maxn],B[maxn],Root[maxn];
  6. int build(int l,int r)
  7. {
  8. int rt = ++np;
  9. Sum[rt] = 0;
  10. if(l < r)
  11. {
  12. int mid = (l + r) / 2;
  13. L[rt] = build(l,mid);
  14. R[rt] = build(mid + 1,r);
  15. }
  16. return rt;
  17. }
  18. int update(int pre,int l,int r,int x)
  19. {
  20. int rt = ++np;
  21. L[rt] = L[pre],R[rt] = R[pre],Sum[rt] = Sum[pre] + 1;
  22. int mid = (l + r) / 2;
  23. if(l < r)
  24. {
  25. if(x <= mid) L[rt] = update(L[pre],l,mid,x);
  26. else R[rt] = update(R[pre],mid + 1,r,x);
  27. }
  28. return rt;
  29. }
  30. int query(int u,int v,int l,int r,int k)
  31. {
  32. if(l >= r) return l;
  33. int mid = (l + r) / 2;
  34. int x = Sum[L[v]] - Sum[L[u]];
  35. if(x >= k) return query(L[u],L[v],l,mid,k);
  36. else return query(R[u],R[v],mid + 1,r,k - x);
  37. }
  38. int main()
  39. {
  40. int T;
  41. scanf("%d",&T);
  42. while(T--)
  43. {
  44. np = 0;
  45. scanf("%d %d",&n,&m);
  46. for(int i = 1;i <= n;i++)
  47. {
  48. scanf("%d",&A[i]);
  49. B[i] = A[i];
  50. }
  51. sort(B + 1,B + 1 + n);
  52. int len = unique(B + 1,B + 1 + n) - (B + 1);
  53. Root[0] = build(1,len);
  54. for(int i = 1;i <= n;i++)
  55. {
  56. int p = lower_bound(B + 1,B + 1 + len,A[i]) - B;
  57. Root[i] = update(Root[i - 1],1,len,p);
  58. }
  59. while(m--)
  60. {
  61. int x,y,z;
  62. scanf("%d %d %d",&x,&y,&z);
  63. int p = query(Root[x - 1],Root[y],1,len,z);
  64. printf("%d\n",B[p]);
  65. }
  66. }
  67. return 0;
  68. }

线性基

线性基的性质:
1、原序列里面的任意一个数都可以由线性基里面的一些数异或得到。
2、线性基里面的任意一些数异或起来都不能得到0。
3、线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的。

  1. struct LineBase
  2. {
  3. ll b[66];//上三角矩阵
  4. ll p[66];//对角矩阵
  5. int cnt;
  6. int max_b = 63;
  7. void init()
  8. {
  9. memset(b,0,sizeof(b));
  10. memset(p,0,sizeof(p));
  11. cnt = 0;
  12. }
  13. bool Insert(ll x)//插入
  14. {
  15. for(int i = max_b;i >= 0;i--)
  16. {
  17. if((x>>i)&1)
  18. {
  19. if(b[i] == 0)
  20. {
  21. b[i] = x;
  22. break;
  23. }
  24. x = x^b[i];
  25. }
  26. }
  27. if(x > 0) cnt++;
  28. return (x > 0);
  29. }
  30. LineBase Merge(LineBase n1,LineBase n2)//线性基合并
  31. {
  32. LineBase ret = n1;
  33. for(int i = 0;i <= max_b;i++)
  34. {
  35. if(n2.b[i]) ret.Insert(n2.b[i]);
  36. }
  37. return ret;
  38. }
  39. LineBase Merge2(LineBase A,LineBase B)//线性基求交
  40. {
  41. LineBase All,C,D;
  42. All.init();
  43. C.init();
  44. D.init();
  45. for(ll i = 60;i >= 0;i--)
  46. {
  47. All.b[i] = A.b[i];
  48. D.b[i] = 1ll<<i;
  49. }
  50. for(ll i = 60;i >= 0;i--)
  51. {
  52. if(B.b[i])
  53. {
  54. ll v = B.b[i],k = 0;
  55. bool can = true;
  56. for(ll j = 60;j >= 0;j--)
  57. {
  58. if(v & (1ll<<j))
  59. {
  60. if(All.b[j])
  61. {
  62. v^=All.b[j];
  63. k^=D.b[j];
  64. }
  65. else
  66. {
  67. can = false;
  68. All.b[j] = v;
  69. D.b[j] = k;
  70. break;
  71. }
  72. }
  73. }
  74. if(can)
  75. {
  76. ll v = 0;
  77. for(ll j = 60;j >= 0;j--)
  78. {
  79. if(k & (1ll<<j))
  80. {
  81. v^=A.b[j];
  82. }
  83. }
  84. C.Insert(v);
  85. }
  86. }
  87. }
  88. return C;
  89. }
  90. ll queryMax(ll x)//求最大
  91. {
  92. ll ans = x;
  93. for(int i = max_b;i >= 0;i--)
  94. {
  95. if((ans^b[i]) > ans) ans^=b[i];
  96. }
  97. return ans;
  98. }
  99. ll queryMin()//求最小
  100. {
  101. for(int i = 0;i < max_b;i++)
  102. {
  103. if(b[i]) return b[i];
  104. }
  105. return 0;
  106. }
  107. void rebuild()//化为对角矩阵
  108. {
  109. for(int i = max_b;i >= 0;i--)
  110. {
  111. for(int j = i - 1;j >= 0;j--)
  112. {
  113. if(b[i]&(1ll<<j)) b[i]^=b[j];
  114. }
  115. }
  116. cnt = 0;
  117. for(int i = 0;i <= max_b;i++)
  118. {
  119. if(b[i]) p[cnt++] = b[i];
  120. }
  121. }
  122. ll kthquery(ll k)//求第k大(必须先化为对角矩阵)
  123. {
  124. ll ans = 0;
  125. if(k >= (1ll<<cnt)) return -1;
  126. for(int i = max_b;i >= 0;i--)
  127. {
  128. if(k&(1ll<<i)) ans^=p[i];
  129. }
  130. return ans;
  131. }
  132. };

杜教BM

输入前几项数据,快速求解线性递推式的第n项。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. namespace linear_seq
  4. {
  5. #define rep(i,a,n) for(int i = a;i < n;i++)
  6. #define per(i,a,n) for(int i = n - 1;i >= a;i--)
  7. #define pb push_back
  8. #define mp make_pari
  9. #define all(x) (x).begin(),(x).end()
  10. #define fi first
  11. #define se second
  12. #define SZ(x) ((int)(x).size())
  13. typedef vector<int> VI;
  14. typedef pair<int,int> PII;
  15. typedef long long ll;
  16. const ll mod = 1e9 + 7;
  17. const int N = 100010;
  18. ll res[N],base[N],_c[N],_md[N];
  19. ll modpow(ll a,ll b,ll mod) {ll res = 1;a %= mod;for(;b;b>>=1){if(b&1)res = res*a%mod;a=a*a%mod;}return res;}
  20. vector<int> Md;
  21. void mul(ll *a,ll *b,ll k)
  22. {
  23. rep(i,0,k+k) _c[i] = 0;
  24. rep(i,0,k) if(a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
  25. for(int i = k+k-1;i>=k;i--) if(_c[i])
  26. rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
  27. rep(i,0,k) a[i]=_c[i];
  28. }
  29. int solve(ll n,VI a,VI b)
  30. {
  31. ll ans=0,pnt=0;
  32. int k=SZ(a);
  33. rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
  34. Md.clear();
  35. rep(i,0,k) if(_md[i]!=0) Md.push_back(i);
  36. rep(i,0,k) res[i]=base[i]=0;
  37. res[0]=1;
  38. while((1ll<<pnt)<=n) pnt++;
  39. for(int p=pnt;p>=0;p--)
  40. {
  41. mul(res,res,k);
  42. if((n>>p)&1)
  43. {
  44. for(int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
  45. rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
  46. }
  47. }
  48. rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
  49. if(ans<0) ans+=mod;
  50. return ans;
  51. }
  52. VI BM(VI s)
  53. {
  54. VI C(1,1),B(1,1);
  55. int L=0,m=1,b=1;
  56. rep(n,0,SZ(s))
  57. {
  58. ll d=0;
  59. rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
  60. if(d==0) ++m;
  61. else if(2*L<=n)
  62. {
  63. VI T=C;
  64. ll c=mod-d*modpow(b,mod-2,mod)%mod;
  65. while(SZ(C)<SZ(B)+m) C.pb(0);
  66. rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
  67. L=n+1-L;B=T;b=d;m=1;
  68. }
  69. else
  70. {
  71. ll c=mod-d*modpow(b,mod-2,mod)%mod;
  72. while(SZ(C)<SZ(B)+m) C.pb(0);
  73. rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
  74. ++m;
  75. }
  76. }
  77. return C;
  78. }
  79. int gao(VI a,ll n)
  80. {
  81. VI c=BM(a);
  82. c.erase(c.begin());
  83. rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
  84. return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
  85. }
  86. }
  87. typedef long long ll;
  88. const int MOD = 1e9 + 7;
  89. ll n,k;
  90. ll dp[2050];
  91. ll powMod(ll a,ll b)
  92. {
  93. ll res = 1;
  94. while(b)
  95. {
  96. if(b % 2 == 1) res = res * a % MOD;
  97. a = a * a % MOD;
  98. b /= 2;
  99. }
  100. return res;
  101. }
  102. int main()
  103. {
  104. int T;
  105. scanf("%d",&T);
  106. while(T--)
  107. {
  108. scanf("%lld %lld",&k,&n);
  109. if(n == -1)
  110. {
  111. ll ans = 2;
  112. ans = ans * powMod(k + 1,MOD - 2) % MOD;
  113. printf("%lld\n",ans);
  114. continue;
  115. }
  116. ll p = powMod(k,MOD - 2);
  117. //把递推式的前2 * k项计算出来并放入vetor中
  118. vector<int>v;
  119. v.push_back(1);
  120. dp[0] = 1;
  121. for(int i = 1;i <= 2 * k;i++)
  122. {
  123. dp[i] = 0;
  124. for(int j = i - 1;j >= max(0ll,i - k);j--)
  125. {
  126. dp[i] = (dp[i] + dp[j] * p % MOD) % MOD;
  127. }
  128. v.push_back(dp[i]);
  129. }
  130. //调用函数计算得到第n项的值
  131. ll ans = linear_seq::gao(v,n);
  132. printf("%lld\n",ans);
  133. }
  134. return 0;
  135. }

解线性同余方程

ans * ans =(同余) n % p

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. ll w;
  5. ll p;
  6. bool ok;
  7. ll powMod(ll a,ll b)
  8. {
  9. ll res = 1;
  10. while(b)
  11. {
  12. if(b&1) res = res * a % p;
  13. a = a * a % p;
  14. b /= 2;
  15. }
  16. return res;
  17. }
  18. struct QuadraticField
  19. {
  20. ll x,y;
  21. QuadraticField operator*(QuadraticField T)
  22. {
  23. QuadraticField ans;
  24. ans.x = (this->x * T.x % p + this->y * T.y % p * w % p) % p;
  25. ans.y = (this->x * T.y % p + this->y * T.x % p) % p;
  26. return ans;
  27. }
  28. QuadraticField operator^(ll b)
  29. {
  30. QuadraticField ans;
  31. QuadraticField a = *this;
  32. ans.x = 1;
  33. ans.y = 0;
  34. while(b)
  35. {
  36. if(b & 1)
  37. {
  38. ans = ans * a;
  39. b--;
  40. }
  41. b /= 2;
  42. a = a * a;
  43. }
  44. return ans;
  45. }
  46. };
  47. ll Lengender(ll a)
  48. {
  49. ll ans = powMod(a,(p - 1) / 2);
  50. if(ans + 1 == p) return -1;
  51. else return ans;
  52. }
  53. ll GetW(ll n,ll a)
  54. {
  55. return ((a * a - n) % p + p) % p;
  56. }
  57. ll Solve(ll n)
  58. {
  59. ll a;
  60. if(p == 2) return n;
  61. if(Lengender(n) == -1) ok = false;
  62. srand((unsigned)time(NULL));
  63. while(1)
  64. {
  65. a = rand() % p;
  66. w = GetW(n,a);
  67. if(Lengender(w) == -1) break;
  68. }
  69. QuadraticField ans,res;
  70. res.x = a;
  71. res.y = 1;
  72. ans = res ^ ((p + 1) / 2);
  73. return ans.x;
  74. }
  75. int main()
  76. {
  77. ll n,ans1,ans2;
  78. while(scanf("%lld %lld",&n,&p) != EOF)
  79. {
  80. ok = true;
  81. n %= p;
  82. ans1 = Solve(n);
  83. ans2 = p - ans1;
  84. if(!ok) printf("-1\n");
  85. else printf("%lld %lld\n",ans1,ans2);
  86. }
  87. return 0;
  88. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注