├── README.md ├── 杂项 ├── 状压枚举真子集.py ├── What to Debug.txt ├── 打表大师.py ├── 卡常大师.cpp ├── BM递推.cpp └── fastIO.cpp ├── 数学 ├── fast_gcd.cpp ├── 快速幂.h ├── 扩展欧几里得 │ ├── 扩展欧几里得.cpp │ ├── 中国剩余定理.cpp │ └── excrt.cpp ├── 线性筛素数2.cpp ├── 欧拉函数(打表版).cpp ├── 组合数取模.cpp ├── Cantor expansion康拓展开.cpp ├── 高斯消元.cpp ├── 线性筛素数.cpp ├── 矩阵乘法模板.h ├── 拉格朗日插值.cpp ├── 同余方程组(不互质).cpp ├── 二次剩余(p%4==3).cpp ├── Miller_Rabin素数测试.cpp ├── 欧拉降幂(含sqrt n的欧拉函数求法).cpp ├── 线性基.cpp ├── 多项式.cpp ├── 分解质因数求lcm.cpp └── Pollard_Rho.cpp ├── 数据结构 ├── 带次顶的栈.cpp ├── 后缀数组.cpp ├── 单调栈-最小值的区间.cpp ├── 值域分块.cpp ├── 堆(STL优先队列).cpp ├── 树状数组 │ ├── 洛谷P3368 【模板】树状数组 2.cpp │ └── 洛谷P3374 【模板】树状数组 1.cpp ├── rmqindex-ST.cpp ├── rmq-ST算法.cpp ├── 堆(手写).cpp ├── 二维ST表.cpp ├── 线段树 │ ├── 洛谷P3372 【模板】线段树 1.cpp │ ├── 线段树(真·两倍空间).cpp │ └── 洛谷P3373 【模板】线段树 2.cpp ├── 带修改莫队.cpp ├── 主席树(区间k大值).cpp ├── 普通有旋Treap.cpp ├── 无旋Treap.cpp └── 虚树.cpp ├── 没什么用 ├── gets.h ├── 并查集.cpp ├── 邻接表.cpp ├── 二分查找.cpp ├── 全排列生成(非DFS).cpp ├── 文本分割.cpp ├── 三分查找.cpp ├── 快速排序.cpp ├── 常用STL.cpp ├── 二路归并.cpp ├── 01背包.cpp └── 循环串的逆序对数目.cpp ├── 字符串 ├── 最小表示法.h ├── manacher.cpp ├── KMP.cpp └── AC自动机.cpp ├── 交互器 ├── test.cpp └── checker.py ├── 动态规划 ├── 树形背包.cpp ├── 最长上升子序列O(n log n).cpp └── 数位DP(不要62).cpp ├── 图论 ├── 最短路 │ ├── Floyd.cpp │ ├── SPFA.cpp │ └── 堆优化SPFA.cpp ├── 邻接矩阵.cpp ├── 二分图 │ ├── 洛谷P3386 【模板】二分图匹配.cpp │ ├── 最小点覆盖(求方案).cpp │ └── KM算法-bfs.cpp ├── 拓扑排序.cpp ├── 树的直径.cpp ├── 种类并查集.cpp ├── 最小生成树 │ ├── Kruskal.cpp │ └── Prim.cpp ├── 割点.cpp ├── 2-sat.cpp ├── 支配树.cpp ├── LCA │ ├── 离线LCA-Tarjan.cpp │ ├── 倍增LCA.cpp │ └── 离线LCA-RMQ-ST.cpp ├── 桥.cpp ├── 强连通分量(Tarjan).cpp ├── 网络流 │ ├── 最大流dinic.cpp │ ├── Dijkstra费用流.cpp │ └── 最小费用最大流.cpp ├── 曼哈顿最小生成树.cpp └── 缩点(Tarjan强连通分量).cpp ├── 容易写错 └── 二分答案的几种写法.cpp ├── genmd.py ├── 计算几何 ├── 二维凸包模板.cpp └── 半平面交.cpp └── 高精度 └── 高精加法乘法-函数.cpp /README.md: -------------------------------------------------------------------------------- 1 | # CYY's algorithm template 2 | -------------------------------------------------------------------------------- /杂项/状压枚举真子集.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | s = x 3 | while (s): 4 | s = x & (s - 1) 5 | print(bin(s)) 6 | -------------------------------------------------------------------------------- /数学/fast_gcd.cpp: -------------------------------------------------------------------------------- 1 | long long gcd(long long a,long long b) { 2 | while (b^=a^=b^=a%=b); 3 | return a; 4 | } 5 | -------------------------------------------------------------------------------- /数学/快速幂.h: -------------------------------------------------------------------------------- 1 | int qpow(int a, int b){ 2 | int ans = 1; 3 | while(b>0){ 4 | if(b % 2)ans = ans * a; 5 | b = b/2; 6 | a = a * a; 7 | } 8 | return ans; 9 | } -------------------------------------------------------------------------------- /数学/扩展欧几里得/扩展欧几里得.cpp: -------------------------------------------------------------------------------- 1 | int exgcd(int a,int b,int &x,int &y) { 2 | if (b == 0) { 3 | x = 1; 4 | y = 0; 5 | return a; 6 | } 7 | else { 8 | int t = exgcd(b,a%b,y,x); 9 | y -= x*(a/b); 10 | return t; 11 | } 12 | } -------------------------------------------------------------------------------- /数据结构/带次顶的栈.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class mystack : public stack { 3 | public: 4 | T sec() { 5 | T tmp = this->top(); 6 | this->pop(); 7 | T sec = this->top(); 8 | this->push(tmp); 9 | return sec; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /杂项/What to Debug.txt: -------------------------------------------------------------------------------- 1 | /* 2 | What to Debug 3 | 1. 读题 4 | 2. 编译加上-Wall -Wshadow -Wextra -fsanitizer=address,看错误信息 5 | 3. 快读 6 | 4. 数组越界 7 | 5. 爆int、爆long long 8 | 6. 数组初始化 9 | 7. 边缘数据 10 | 8. 输出格式 11 | 9. 输入是否需要排序(即便样例排了序 12 | 10. 祝1A 13 | */ 14 | -------------------------------------------------------------------------------- /没什么用/gets.h: -------------------------------------------------------------------------------- 1 | namespace cyy { 2 | bool gets(char *s) { 3 | char c = getchar(); 4 | if (c == EOF) return false; 5 | while (c != '\n' && c != EOF) { 6 | *s = c; 7 | s ++; 8 | c = getchar(); 9 | } 10 | *s = '\0'; 11 | return true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /数学/线性筛素数2.cpp: -------------------------------------------------------------------------------- 1 | bool judge[1000005]; 2 | vector primes; 3 | inline void getprime(int x) { 4 | judge[1] = true; 5 | for (int i=2;i<=x;i++) { 6 | if (!judge[i]) primes.push_back(i); 7 | for (auto p:primes) { 8 | if (i * p > x) break; 9 | judge[i*p] = true; 10 | if (i % p == 0) break; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /字符串/最小表示法.h: -------------------------------------------------------------------------------- 1 | int strmin(char *s) {//给一个字符串s,返回字典序最小循环子串的开始位置 2 | int i=0,j=1,k=0; 3 | int len = strlen(s); 4 | while (i < len && j < len && k < len) { 5 | int d = s[(i+k)%len] - s[(j+k)%len]; 6 | if (d == 0) k ++; 7 | else { 8 | if (d > 0) i = i + k + 1; 9 | else j = j + k + 1; 10 | if (i == j) j ++; 11 | k = 0; 12 | } 13 | } 14 | return min(i,j); 15 | } 16 | -------------------------------------------------------------------------------- /数学/欧拉函数(打表版).cpp: -------------------------------------------------------------------------------- 1 | //欧拉函数的定义为小于等于x的数中有多少个数与x互质 2 | #include 3 | using namespace std; 4 | int phi[40005]; 5 | int main() { 6 | int n; 7 | cin >> n; 8 | phi[1] = 1; 9 | for (int i=2;i<=n;i++) { 10 | if (phi[i] == 0) for (int j=i;j<=n;j+=i) { 11 | if (phi[j] == 0) phi[j] = j; 12 | phi[j] = phi[j] / i * (i - 1); 13 | } 14 | } 15 | cout << phi[n] << endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /交互器/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int ask(int x) { 4 | printf("%d\n",x); 5 | fflush(stdout); 6 | int res; 7 | scanf("%d",&res); 8 | return res; 9 | } 10 | int main() { 11 | int l = 1, r = 1000; 12 | while (l <= r) { 13 | int mid = (l + r) >> 1; 14 | int res = ask(mid); 15 | if (res == 0) { 16 | break; 17 | } 18 | else if (res == -1) { 19 | l = mid + 1; 20 | } 21 | else { 22 | r = mid - 1; 23 | } 24 | } 25 | return 0; 26 | } -------------------------------------------------------------------------------- /数据结构/后缀数组.cpp: -------------------------------------------------------------------------------- 1 | //untested 2 | #define val first 3 | #define id second 4 | void sort_suffix(int s[],int n,int rk[]) { 5 | static pair sa[maxn];//用于后缀数组排序 6 | for (int i=1;i<=n;i++) { 7 | sa[i].id = i; 8 | sa[i].val = s[i]; 9 | } 10 | sort(sa+1,sa+1+n); 11 | for (int i=1;i<=n;i++) rk[sa[i].id] = i; 12 | for (int d=1;d<=n;d<<=1) { 13 | for (int i=1;i<=n;i++) { 14 | sa[i].val = rk[sa[i].id] * (n+1) + ((i+d<=n)?rk[sa[i+d].id]:0); 15 | } 16 | sort(sa+1,sa+1+n); 17 | for (int i=1;i<=n;i++) rk[sa[i].id] = i; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /动态规划/树形背包.cpp: -------------------------------------------------------------------------------- 1 | //Luogu P2014:给出每个物品的价值和所属关系(如果父节点为0则没有所属关系,若不为0则存在父节点),求选M个物品能获得的最大权值 2 | #include 3 | using namespace std; 4 | int f[305][305]; 5 | int n,m; 6 | vector g[305]; 7 | int s[305]; 8 | void dfs(int u) { 9 | for (auto v:g[u]) { 10 | for (int i=0;i<=m-1;i++) f[v][i] = f[u][i] + s[v]; 11 | dfs(v); 12 | for (int i=m;i>=1;i--) f[u][i] = max(f[u][i],f[v][i-1]); 13 | } 14 | } 15 | int main() { 16 | scanf("%d%d",&n,&m); 17 | for (int i=1;i<=n;i++) { 18 | int ki; 19 | scanf("%d%d",&ki,&s[i]); 20 | g[ki].push_back(i); 21 | } 22 | dfs(0); 23 | printf("%d\n",f[0][m]); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /动态规划/最长上升子序列O(n log n).cpp: -------------------------------------------------------------------------------- 1 | //http://poj.org/problem?id=1631 2 | #include 3 | #include 4 | using namespace std; 5 | int a[40005]; 6 | int s[40005]; 7 | int main() { 8 | int T; 9 | scanf("%d",&T); 10 | while (T --) { 11 | int n; 12 | scanf("%d",&n); 13 | for (int i=0;i s[tail]) { 18 | s[++tail] = a[i]; 19 | continue; 20 | } 21 | int p = upper_bound(s,s+tail,a[i]) - s; 22 | //上面的upper_bound实际上范围不包括最后一个元素 23 | s[p] = a[i]; 24 | } 25 | printf("%d\n",tail); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /没什么用/并查集.cpp: -------------------------------------------------------------------------------- 1 | //洛谷P3367 【模板】并查集 2 | #include 3 | int family[10005]; 4 | int find(int member){ 5 | if (family[member] == member) return member; 6 | else { 7 | family[member] = find(family[member]); 8 | return family[member]; 9 | } 10 | } 11 | int main() { 12 | int N,M; 13 | scanf("%d%d",&N,&M); 14 | for (int i=1;i<=N;i++) family[i] = i;//初始化并查集 15 | for (int i=0;i 2 | using namespace std; 3 | int g[105][105]; 4 | int main() { 5 | int n; 6 | cin >> n; 7 | for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) cin >> g[i][j];//输入整个邻接矩阵 8 | //输入数据中-1表示没有这条边,即无穷大,这里不使用0x3f,而使用NOIP初赛常用的-1作为无穷大,下面判断即可 9 | for (int k=1;k<=n;k++) 10 | for (int i=1;i<=n;i++) 11 | for (int j=1;j<=n;j++) 12 | if (k != i && i != j && j != k && g[i][k] != -1 && g[k][j] != -1 && g[i][j] > g[i][k]+g[k][j]) g[i][j],g[i][k]+g[k][j]; 13 | //思想:更小的路径一定是经过了一条更短的路径相连 14 | for (int i=1;i<=n;i++) { 15 | for (int j=1;j<=n;j++) cout << g[i][j] << " "; 16 | cout << endl;//打出整个邻接矩阵 17 | } 18 | return 0; 19 | } -------------------------------------------------------------------------------- /数据结构/单调栈-最小值的区间.cpp: -------------------------------------------------------------------------------- 1 | void work_R() { 2 | stack s; 3 | for (int i=1;i<=n;i++) { 4 | while (!s.empty()) { 5 | if (a[s.top()] > a[i]) { 6 | R[s.top()] = i - 1; 7 | s.pop(); 8 | } 9 | else break; 10 | } 11 | s.push(i); 12 | } 13 | while (!s.empty()) { 14 | R[s.top()] = n; 15 | s.pop(); 16 | } 17 | } 18 | void work_L() { 19 | stack s; 20 | for (int i=n;i>=1;i--) { 21 | while (!s.empty()) { 22 | if (a[s.top()] > a[i]) { 23 | L[s.top()] = i + 1; 24 | s.pop(); 25 | } 26 | else break; 27 | } 28 | s.push(i); 29 | } 30 | while (!s.empty()) { 31 | L[s.top()] = 1; 32 | s.pop(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /没什么用/邻接表.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | struct Edge {//点权化为边权 5 | int to; 6 | int w; 7 | int next; 8 | }; 9 | Edge e[1005]; 10 | int pre[105]; 11 | int main() { 12 | memset(pre,-1,sizeof(pre)); 13 | int n,m; 14 | cin >> n >> m; 15 | for (int i=0;i> u >> v >> w; 18 | e[i].to = v; 19 | e[i].w = w; 20 | e[i].next = pre[u]; 21 | pre[u] = i; 22 | } 23 | while(true) { 24 | int node; 25 | cin >> node;//输入要查询的节点 26 | for (int i = pre[node]; i != -1 ; i = e[i].next) { 27 | cout << node << "->" << e[i].to << " weight=" << e[i].w << endl; 28 | } 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /图论/邻接矩阵.cpp: -------------------------------------------------------------------------------- 1 | //邻接矩阵 2 | #include 3 | using namespace std; 4 | int main(){ 5 | int matrix[20][20]; 6 | memset(matrix,0x7f,sizeof(matrix));//若处理数据时需要相加,请使用0x3f 7 | //需要注意的是,0x7f并不是int的最大值 8 | //注意,输入时应考虑数组越界问题 9 | int n; 10 | cin >> n; 11 | for (int i=0;i> start >> end >> weight; 14 | matrix[start][end] = weight;//有向图,若为无向图请uncomment下一行 15 | //matrix[start][end] = weight; 16 | } 17 | while (true){ 18 | //在这里,你可以输入数据来查询 19 | int start,end; 20 | cin >> start >> end; 21 | cout << start << "->" << end << " weight=" << matrix[start][end] << endl; 22 | } 23 | //使用control+c退出 24 | return 0; 25 | } -------------------------------------------------------------------------------- /没什么用/二分查找.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | int main(){ 5 | int n; 6 | cin >> n; 7 | vector array; 8 | for (int i=0;i> t; 11 | array.push_back(t); 12 | } 13 | int key;//要查找的数 14 | cin >> key; 15 | int left = 0, right = n-1; 16 | while(left <= right){//防止没找到的情况陷入死循环 17 | int mid = (left + right) / 2; 18 | if (array[mid] < key) left = mid + 1;//array[mid]值太小了,把二分区间左边调整到当前查找数字的右边 19 | else if (array[mid] > key) right = mid - 1;//array[mid]值太大了,把二分区间右边调整到当前查找数字的左边 20 | else { 21 | cout << "Postion:" << mid << endl;//输出位置 22 | break; 23 | } 24 | } 25 | return 0; 26 | } -------------------------------------------------------------------------------- /没什么用/全排列生成(非DFS).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace cyy { 3 | bool next_permutation(int *a,int *b) { 4 | b --; 5 | int* p = b; 6 | while (p != a && *(p - 1) >= *p) p --; 7 | if (p == a) return false; 8 | for (int* p1 = b;p1>=p;p1--) { 9 | if (*p1 > *(p-1)) { 10 | std::swap(*p1,*(p-1)); 11 | break; 12 | } 13 | } 14 | std::sort(p,b+1); 15 | return true; 16 | } 17 | }; 18 | int main() { 19 | int a[10],b[10]; 20 | for (int i=1;i<=10;i++) a[i-1] = i,b[i-1] = i; 21 | do { 22 | for (int i=0;i<10;i++) if (a[i] != b[i]) { 23 | printf("error\n"); 24 | } 25 | cyy::next_permutation(a,a+10); 26 | } 27 | while (std::next_permutation(b,b+10)); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /杂项/打表大师.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #用于打表时压缩数据 3 | #Usage: 4 | #1. 将打表的答案每行一个十进制数字输出到文件,例如文件名为1.txt 5 | #2. 执行该文件,比如文件名为comp.py,执行python3 comp.py < 1.txt > biao.py 6 | #为了更好压缩效果,可尝试将gzip改为bz2 7 | import base64 8 | import gzip 9 | a = bytearray() 10 | while True: 11 | try: 12 | x = int(input()) 13 | a.append((x>>24) & 0xff) 14 | a.append((x>>16) & 0xff) 15 | a.append((x>>8) & 0xff) 16 | a.append((x>>0) & 0xff) 17 | except: 18 | break 19 | zip_result = gzip.compress(a) 20 | print("import base64\nimport gzip\ntmp = gzip.decompress(base64.b64decode({}))\narr = []\nfor i in range(len(tmp)//4):\n\tarr.append((tmp[i*4]<<24)|(tmp[i*4+1]<<16)|(tmp[i*4+2]<<8)|tmp[i*4+3])".format(base64.b64encode(zip_result))) 21 | -------------------------------------------------------------------------------- /数据结构/值域分块.cpp: -------------------------------------------------------------------------------- 1 | struct value_block { 2 | int blk_sum[1000]; 3 | int cnt[maxn]; 4 | void clear() { 5 | for (int i=0;i= n) return; 13 | if (cnt[x] == 0) { 14 | blk_sum[x/blk] ++; 15 | } 16 | cnt[x] ++; 17 | } 18 | void del(int x) { 19 | if (x >= n) return; 20 | if (cnt[x] == 1) { 21 | blk_sum[x/blk] --; 22 | } 23 | cnt[x] --; 24 | } 25 | int mex() { 26 | for (int i=0;i>= 1; 11 | a *= a; 12 | a %= mo; 13 | } 14 | return ret; 15 | } 16 | long long c(long long n,long long m) { 17 | if (n < 0 || m < 0 || m > n) return 0; 18 | return (((fac[n] * inv[m]) % mo) * inv[n-m]) % mo; 19 | } 20 | void init() { 21 | fac[0] = 1; 22 | for (int i=1;i<=100000;i++) { 23 | fac[i] = fac[i-1] * i; 24 | fac[i] %= mo; 25 | } 26 | inv[100000] = qpow(fac[100000],mo-2); 27 | for (int i=100000-1;i>=0;i--) { 28 | inv[i] = inv[i+1] * (i + 1LL); 29 | inv[i] %= mo; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /没什么用/文本分割.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | int main(){ 6 | string str = "I love you"; 7 | string separator = " "; 8 | vector result; 9 | int i=0; 10 | string temp = ""; 11 | while(i != str.length()){ 12 | if (str[i] == separator[0]){ 13 | if (str.substr(i,separator.size()) == separator){ 14 | //matched 15 | i += separator.length(); 16 | result.push_back(temp); 17 | temp = ""; 18 | continue; 19 | } 20 | } 21 | temp += str[i]; 22 | i++; 23 | } 24 | if (temp != ""){ 25 | result.push_back(temp); 26 | } 27 | for (int i=0;i 3 | using namespace std; 4 | const double eps = 1e-6; 5 | int n; 6 | double a[14]; 7 | inline double f(double x) { 8 | double ret = 0; 9 | for (int i=0;i<=n;i++) ret += a[i] * pow(x,n-i); 10 | return ret; 11 | } 12 | inline bool equal(double a,double b) { 13 | if (abs(a-b) < eps) return true; 14 | else return false; 15 | } 16 | int main() { 17 | double l,r; 18 | scanf("%d%lf%lf",&n,&l,&r); 19 | for (int i=0;i<=n;i++) scanf("%lf",&a[i]); 20 | while (!equal(l,r)) { 21 | double mid1 = l + (r-l)/3; 22 | double mid2 = l + 2 * (r-l) / 3; 23 | 24 | if (f(mid1) > f(mid2)) r = mid2; 25 | else l = mid1; 26 | } 27 | printf("%0.5lf\n",l); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /图论/二分图/洛谷P3386 【模板】二分图匹配.cpp: -------------------------------------------------------------------------------- 1 | //匈牙利算法,寻找增广路 2 | #include 3 | using namespace std; 4 | int n,m; 5 | vector g[1005]; 6 | bool vis[1005]; 7 | int pre[1005]; 8 | bool zg(int u) { 9 | for(auto v:g[u]) { 10 | if (!vis[v]) { 11 | vis[v] = true; 12 | if (pre[v] == 0 || zg(pre[v])) { 13 | pre[v] = u; 14 | return true; 15 | } 16 | } 17 | } 18 | return false; 19 | } 20 | int main() { 21 | int e; 22 | scanf("%d%d%d",&n,&m,&e); 23 | for (int i=0;i= 1 && m >= 1 && u <= n && v <= m) g[u].push_back(v); 27 | } 28 | int ans = 0; 29 | for (int i=1;i<=n;i++) { 30 | memset(vis,0,sizeof(vis)); 31 | if (zg(i)) ans ++; 32 | } 33 | printf("%d\n",ans); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /字符串/manacher.cpp: -------------------------------------------------------------------------------- 1 | //给一个字符串s,求最长回文串的长度 2 | #include 3 | using namespace std; 4 | char a[11000005]; 5 | char b[22000010]; 6 | int p[22000010]; 7 | int lena,lenb; 8 | int main() { 9 | scanf("%s",a); 10 | lena = strlen(a); 11 | b[0] = '$'; 12 | b[1] = '#'; 13 | int j = 2; 14 | for (int i=0;i 2 | using namespace std; 3 | long long getcantor(int arr[],int len) { 4 | long long xs = 1;//系数 5 | for (int i=2;i<=len-1;i++) xs *= i; 6 | long long ret = 0; 7 | for (int i=0;i 2 | int n; 3 | int a[500000];//差分存储,树状数组维护 4 | inline int lowbit(int n) { 5 | return n&(-n); 6 | } 7 | inline void add(int x,int d) { 8 | for (int i=x;i<=n;i+=lowbit(i)) a[i] += d; 9 | } 10 | inline int query(int x) { 11 | int ret = 0; 12 | for (int i=x;i>=1;i-=lowbit(i)) ret += a[i]; 13 | return ret; 14 | } 15 | int main() { 16 | int m; 17 | scanf("%d%d",&n,&m); 18 | for (int i=1;i<=n;i++) { 19 | int t; 20 | scanf("%d",&t); 21 | add(i,t); 22 | add(i+1,-t); 23 | } 24 | while(m--) { 25 | int o; 26 | scanf("%d",&o); 27 | if (o == 1) { 28 | int x,y,k; 29 | scanf("%d%d%d",&x,&y,&k); 30 | add(x,k); 31 | add(y+1,-k); 32 | } 33 | else { 34 | int x; 35 | scanf("%d",&x); 36 | printf("%d\n",query(x)); 37 | } 38 | } 39 | return 0; 40 | } -------------------------------------------------------------------------------- /字符串/KMP.cpp: -------------------------------------------------------------------------------- 1 | //Luogu P3375:给出两个字符串T和P,其中P为T的子串,求出P在T中所有出现的位置。 2 | #include 3 | char T[1000005]; 4 | char P[1000005]; 5 | int jump[1000005]; 6 | int n,m; 7 | void getnext() { 8 | jump[0] = -1; 9 | int k = -1; 10 | for (int i=1;i 2 | using std::swap; 3 | #define eps 1e-8 4 | int n; 5 | double a[105][105]; 6 | bool gauss() { 7 | for (int i=0;i fabs(a[k][i])) k = j; 10 | double now = a[k][i]; 11 | if (fabs(now) < eps) return false; 12 | for (int j=i;j<=n;j++) swap(a[i][j],a[k][j]); 13 | for (int j=i;j<=n;j++) a[i][j] /= now; 14 | for (int k=0;k 2 | int n; 3 | int a[500005]; 4 | inline int lowbit(int x) { 5 | return x&(-x); 6 | } 7 | inline void add(int x,int d) { 8 | for (int i=x;i<=n;i+=lowbit(i)) a[i] += d; 9 | } 10 | inline int sum(int x) { 11 | int ret = 0; 12 | for (int i=x;i>=1;i-=lowbit(i)) ret += a[i]; 13 | return ret; 14 | } 15 | inline int query(int x,int y) { 16 | return sum(y)-sum(x-1); 17 | } 18 | int main() { 19 | int m; 20 | scanf("%d%d",&n,&m); 21 | for (int i=1;i<=n;i++) { 22 | int t; 23 | scanf("%d",&t); 24 | add(i,t); 25 | } 26 | while(m--) { 27 | int o; 28 | scanf("%d",&o); 29 | if (o == 1) { 30 | int x,k; 31 | scanf("%d%d",&x,&k); 32 | add(x,k); 33 | } 34 | else { 35 | int x,y; 36 | scanf("%d%d",&x,&y); 37 | printf("%d\n",query(x,y)); 38 | } 39 | } 40 | return 0; 41 | } -------------------------------------------------------------------------------- /genmd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | header = "# CYY's Algorithm Template" 3 | toc = "" 4 | buf = "" 5 | import os 6 | suffix = ['cpp','py','h','txt'] 7 | curpath = '' 8 | for root,dirs,files in os.walk('.'): 9 | for file in files: 10 | if '/.' in root: 11 | continue 12 | if file == 'genmd.py': 13 | continue 14 | if curpath != root: 15 | buf += '\n# ' + root + "\n" 16 | curpath = root 17 | toc += '- ' + root + "\n" 18 | filename = os.path.join(root,file) 19 | for x in suffix: 20 | if file.endswith('.'+x): 21 | toc += "\t- " + file + "\n" 22 | buf += "\n## " + file + "\n```" + x + "\n" 23 | print(file) 24 | with open(filename, 'r') as f: 25 | buf += f.read() 26 | buf += '\n```\n' 27 | with open('output.md','w') as f: 28 | #f.write(header + "\n" + toc + "\n" + buf) 29 | f.write(header + "\n" + buf) 30 | -------------------------------------------------------------------------------- /数学/扩展欧几里得/中国剩余定理.cpp: -------------------------------------------------------------------------------- 1 | //洛谷P1495 曹冲养猪 2 | /* 3 | ans%a=b 4 | */ 5 | #include 6 | long long exgcd(long long a,long long b,long long &x,long long &y) { 7 | if (b == 0) { 8 | x = 1; 9 | y = 0; 10 | return a; 11 | } 12 | else { 13 | long long ret = exgcd(b,a%b,y,x); 14 | y -= x * (a/b); 15 | return ret; 16 | } 17 | } 18 | long long gcd(long long a,long long b) { 19 | if (b == 0) return a; 20 | else return gcd(b,a%b); 21 | } 22 | int a[10],b[10]; 23 | int main() { 24 | int n; 25 | scanf("%d",&n); 26 | for (int i=0;i 3 | using namespace std; 4 | bool judge[10000005]; 5 | vector prime; 6 | int main() { 7 | int n,m; 8 | scanf("%d%d",&n,&m); 9 | judge[1] = true; 10 | for (int i=2;i<=n;i++) { 11 | if (!judge[i]) prime.push_back(i); 12 | for (auto p:prime) { 13 | if (i * p > n) break; 14 | judge[i*p] = true; 15 | if (i % p == 0) break; 16 | /* 17 | 上一行是最难理解的地方,大概口胡一下: 18 | 如果i%p==0,那么说明i是p本身或者i是一个合数 19 | 那么欧拉筛要保证线性的话,就必须让一个数只能被它最小的质因子筛 20 | 例如,当i=4,p=2时,我们筛掉了8就可以停止了 21 | 此时下一个p=3,尽管4*3==12,但很显然,3并不是12的最小质因子 22 | 而12的最小质因子是2,应该在i==6时被p==2的情况筛掉 23 | 因此当我们做到i%p==0时就可以break了 24 | */ 25 | } 26 | } 27 | while (m --) { 28 | int num; 29 | scanf("%d",&num); 30 | if (judge[num]) printf("No\n"); 31 | else printf("Yes\n"); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /动态规划/数位DP(不要62).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int INF = 0x3f3f3f3f; 4 | int f[10][2]; 5 | int digit[10]; 6 | int dfs(int dep,bool last6,bool uplimited) { 7 | if (dep < 0) return 1; 8 | if (!uplimited && f[dep][last6] != INF) return f[dep][last6]; 9 | int up = 9; 10 | if (uplimited) up = digit[dep]; 11 | int cur = 0; 12 | for (int i=0;i<=up;i++) { 13 | if ( (i == 2 && last6) || i == 4) continue; 14 | cur += dfs(dep-1,i == 6,uplimited && i == up); 15 | } 16 | if (!uplimited) f[dep][last6] = cur; 17 | return cur; 18 | } 19 | int solve(int x) { 20 | int cnt = 0; 21 | while (x) { 22 | digit[cnt++] = x % 10; 23 | x /= 10; 24 | } 25 | return dfs(cnt-1,false,true); 26 | } 27 | int main() { 28 | memset(f,0x3f,sizeof(f)); 29 | int n,m; 30 | while (cin >> n >> m) { 31 | if (n == 0 && m == 0) break; 32 | cout << solve(m) - solve(n-1) << endl; 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /图论/拓扑排序.cpp: -------------------------------------------------------------------------------- 1 | //UVa 10305 - Ordering Tasks 2 | #include 3 | #include 4 | using namespace std; 5 | int main() { 6 | bool g[105][105]; 7 | int indegree[105]; 8 | int stack[105]; 9 | int n,m; 10 | while(scanf("%d%d",&n,&m) == 2) { 11 | if (n == 0 && m == 0) break; 12 | memset(indegree,0,sizeof(indegree)); 13 | memset(g,0,sizeof(g)); 14 | for (int i=0;i 3 | #include 4 | #include 5 | using namespace std; 6 | int a[10005]; 7 | int st[10005][30]; 8 | void initRMQ(int maxn) { 9 | for (int i=0;i v) swap(u,v); 19 | int k = log(v-u+1)/log(2); 20 | int l = st[u][k]; 21 | int r = st[v-int(pow(2,k))+1][k]; 22 | return a[l] < a[r] ? l : r; 23 | } 24 | int main() { 25 | int n; 26 | scanf("%d",&n); 27 | for (int i=0;i 4 | using namespace std; 5 | vector g[100005]; 6 | bool vis[100005]; 7 | int dis[100005]; 8 | int n; 9 | void getdis(int u) { 10 | vis[u] = true; 11 | for (auto v:g[u]) { 12 | if (!vis[v]) { 13 | dis[v] = dis[u] + 1; 14 | getdis(v); 15 | } 16 | } 17 | } 18 | int main() { 19 | int m; 20 | scanf("%d%d",&n,&m); 21 | for (int i=0;i dis[root]) root = i; 31 | memset(dis,0,sizeof(dis)); 32 | memset(vis,false,sizeof(vis)); 33 | getdis(root); 34 | int ans = 0; 35 | for (int i=1;i<=n;i++) ans = max(ans,dis[i]); 36 | printf("%d\n",ans); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /没什么用/快速排序.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using std::swap; 3 | //don't using namespace std 4 | int a[100005]; 5 | void sort(int l,int r) { 6 | int i = l; 7 | int j = r; 8 | int base = a[l+rand()%(r-l+1)]; 9 | while (i <= j) { 10 | while (a[i] < base) i++; 11 | while (a[j] > base) j--; 12 | if (i <= j) { 13 | swap(a[i],a[j]); 14 | i++; 15 | j--; 16 | } 17 | } 18 | if (l < j) sort(l,j); 19 | if (i < r) sort(i,r); 20 | } 21 | int read() { 22 | int f = 1; 23 | char c = getchar(); 24 | int ret = 0; 25 | while (!(c >= '0' && c <= '9')) { 26 | if (c == '-') f = -1; 27 | c = getchar(); 28 | } 29 | while (c >='0' && c <= '9') { 30 | ret = ret * 10 + c - '0'; 31 | c = getchar(); 32 | } 33 | return ret * f; 34 | } 35 | int main() { 36 | srand((unsigned)time(0)); 37 | int n = read(); 38 | for (int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int a[20000]; 12 | vector b; 13 | queue q; 14 | stack s; 15 | 16 | int main() { 17 | int n; 18 | cin >> n; 19 | for(int i=0;i> a[i]; 21 | b.push_back(a[i]); 22 | } 23 | sort(a, a+n); 24 | sort(b.begin(), b.end()); 25 | 26 | for(int i=0;i 3 | using namespace std; 4 | const long long mo = 998244353; 5 | long long qpow(long long a,long long b) { 6 | long long ret = 1; 7 | while (b) { 8 | if (b & 1) { 9 | ret *= a; 10 | ret %= mo; 11 | } 12 | a *= a; 13 | a %= mo; 14 | b >>= 1; 15 | } 16 | return ret; 17 | } 18 | long long x[2000],y[2000]; 19 | int main() { 20 | int n; 21 | long long k; 22 | scanf("%d%lld",&n,&k); 23 | for (int i=0;i 2 | long long exgcd(long long a,long long b,long long &x,long long &y) { 3 | if (b == 0) { 4 | x = 1; 5 | y = 0; 6 | return a; 7 | } 8 | else { 9 | long long ret = exgcd(b,a%b,y,x); 10 | y -= x * (a / b); 11 | return ret; 12 | } 13 | } 14 | int main() { 15 | int k; 16 | while (scanf("%d",&k) == 1) { 17 | long long a1,r1; 18 | scanf("%lld%lld",&a1,&r1); 19 | if (k == 1) { 20 | if (a1 > r1) printf("%lld\n",r1); 21 | else printf("-1\n"); 22 | continue; 23 | } 24 | bool flag = true; 25 | while (-- k) { 26 | long long a2,r2; 27 | scanf("%lld%lld",&a2,&r2); 28 | if (!flag) continue; 29 | long long k1,k2; 30 | long long g = exgcd(a1,a2,k1,k2); 31 | if ((r2 - r1) % g != 0) flag = false; 32 | k1 *= (r2 - r1) / g; 33 | long long xs = a2 / g; 34 | k1 = (k1 % xs + xs) % xs; 35 | r1 += k1 * a1; 36 | a1 = (a1 / g) * a2; 37 | } 38 | if (flag) printf("%lld\n",r1); 39 | else printf("-1\n"); 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /图论/种类并查集.cpp: -------------------------------------------------------------------------------- 1 | //http://poj.org/problem?id=1703 2 | //有N个罪犯,D a,b表示两个罪犯不属于一个帮派,A a,b表示询问a,b的关系 3 | #include 4 | int f[100005]; 5 | int r[100005]; 6 | int find(int x) { 7 | if (f[x] == x) return x; 8 | int t = find(f[x]); 9 | r[x] = (r[x] + r[f[x]]) % 2; 10 | return f[x] = t; 11 | } 12 | void uni(int x,int y) { 13 | int xr = find(x); 14 | int yr = find(y); 15 | f[xr] = yr; 16 | r[xr] = (r[x] + r[y] + 1) % 2; 17 | } 18 | int n,m; 19 | void init() { 20 | for (int i=1;i<=n;i++) { 21 | f[i] = i; 22 | r[i] = 0; 23 | } 24 | } 25 | int main() { 26 | int T; 27 | scanf("%d",&T); 28 | while (T --) { 29 | scanf("%d%d",&n,&m); 30 | init(); 31 | char o; 32 | int x,y; 33 | while (m --) { 34 | scanf(" %c%d%d",&o,&x,&y); 35 | if (o == 'A') { 36 | if (find(x) == find(y)) { 37 | if (r[x] == r[y]) printf("In the same gang.\n"); 38 | else printf("In different gangs.\n"); 39 | } 40 | else printf("Not sure yet.\n"); 41 | } 42 | else uni(x,y); 43 | } 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /没什么用/二路归并.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | int main(){ 5 | int a,b; 6 | cin >> a >> b; 7 | vector set1; 8 | vector set2; 9 | vector result; 10 | for (int i=0;i> temp; 13 | set1.push_back(temp); 14 | } 15 | for (int i=0;i> temp; 18 | set2.push_back(temp); 19 | } 20 | //输入完成 21 | int i = 0;//set1的位置 22 | int j = 0;//set2的位置 23 | while(i != set1.size() || j != set2.size()){ 24 | if (i == set1.size()){ 25 | result.push_back(set2[j]); 26 | j++; 27 | continue; 28 | } 29 | if (j == set2.size()){ 30 | result.push_back(set1[i]); 31 | i++; 32 | continue; 33 | } 34 | if (set1[i] < set2[j]){ 35 | result.push_back(set1[i]); 36 | i++; 37 | } 38 | else{ 39 | result.push_back(set2[j]); 40 | j++; 41 | } 42 | } 43 | for (vector::iterator i=result.begin();i != result.end();i++){ 44 | cout << *i << endl; 45 | } 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /数学/同余方程组(不互质).cpp: -------------------------------------------------------------------------------- 1 | //http://poj.org/problem?id=2891 2 | #include 3 | long long exgcd(long long a,long long b,long long &x,long long &y) { 4 | if (b == 0) { 5 | x = 1; 6 | y = 0; 7 | return a; 8 | } 9 | else { 10 | long long ret = exgcd(b,a%b,y,x); 11 | y -= x * (a / b); 12 | return ret; 13 | } 14 | } 15 | int main() { 16 | int k; 17 | while (scanf("%d",&k) == 1) { 18 | long long a1,r1; 19 | scanf("%lld%lld",&a1,&r1); 20 | if (k == 1) { 21 | if (a1 > r1) printf("%lld\n",r1); 22 | else printf("-1\n"); 23 | continue; 24 | } 25 | bool flag = true; 26 | while (-- k) { 27 | long long a2,r2; 28 | scanf("%lld%lld",&a2,&r2); 29 | if (!flag) continue; 30 | long long k1,k2; 31 | long long g = exgcd(a1,a2,k1,k2); 32 | if ((r2 - r1) % g != 0) flag = false; 33 | k1 *= (r2 - r1) / g; 34 | long long xs = a2 / g; 35 | k1 = (k1 % xs + xs) % xs; 36 | r1 += k1 * a1; 37 | a1 = (a1 / g) * a2; 38 | } 39 | if (flag) printf("%lld\n",r1); 40 | else printf("-1\n"); 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /数学/二次剩余(p%4==3).cpp: -------------------------------------------------------------------------------- 1 | //https://ac.nowcoder.com/acm/contest/889/B 2 | #include 3 | using namespace std; 4 | const long long p = 1000000007; 5 | long long qpow(long long a,long long b) { 6 | long long ret = 1; 7 | while (b) { 8 | if (b & 1) { 9 | ret *= a; 10 | ret %= p; 11 | } 12 | a *= a; 13 | a %= p; 14 | b >>= 1; 15 | } 16 | return ret; 17 | } 18 | long long b,c; 19 | int main() { 20 | int T; 21 | scanf("%d",&T); 22 | while (T --) { 23 | scanf("%lld%lld",&b,&c); 24 | //(x^2-xb+c) % p==0 25 | long long d = ((b * b - 4ll * c) % p + p) % p; 26 | if (d == 0) { 27 | printf("%lld %lld\n",b/2,b/2); 28 | } 29 | else if (qpow(d,(p-1)/2) == 1) { 30 | long long sqrt_d = qpow(d,(p+1)/4);//仅在p%4==3时适用 31 | if ( (b ^ sqrt_d) & 1) sqrt_d = (p - sqrt_d) % p;//奇偶性不同的时候,下一步运算会有问题 32 | long long x = (b - sqrt_d) / 2; 33 | long long y = (b + sqrt_d) / 2; 34 | x = (x % p + p) % p; 35 | y = (y % p + p) % p; 36 | if (x > y) swap(x,y); 37 | printf("%lld %lld\n",x,y); 38 | } 39 | else printf("-1 -1\n"); 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /没什么用/01背包.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define MAXN 100 5 | #define MAXV 100 6 | //MAXN和MAXV根据题目自行调整 7 | using namespace std; 8 | int main(){ 9 | int v;//背包的容积 10 | int n;//物品的数量 11 | cin >> v >> n; 12 | int V[MAXN];//物品的体积(数组下标从1开始)V[i]相当于前文所述的Vi 13 | int P[MAXN];//物品的价值(数组下标从1开始)P[i]相当于前文所述的Pi 14 | for (int i=1;i<=n;i++) cin >> V[i] >> P[i]; 15 | int f[MAXN][MAXV];//用于保存递推过程的数组 16 | memset(f,0,sizeof(f));//清零f数组,特别是f[0]的每项元素都必须为0 17 | for (int i=1;i<=n;i++)//处理编号为i的物品是否要放入背包中 18 | for (int j=1;j<=v;j++)//枚举背包的容积从1到最大值v 19 | if (V[i] <= j) { 20 | //确保该物品可以放入背包(在可能清空别的物品的情况下) 21 | f[i][j] = max(f[i-1][j],f[i-1][j-V[i]]+P[i]); 22 | /*上一行代码特别说明一下: 23 | f[i-1][j]是在本次不放入编号为i的物体情况下背包的内物品的最大价值和。 24 | f[i-1][j-V[i]]是背包在放入编号为i的物品前, 25 | 在背包容积只有j-V[i]的情况下背包内物品的最大价值和, 26 | 这样就明白为什么要从1开始枚举背包的容积到最大值v了吧。 27 | P[i]不必多言,还要再放上该物品,因此要加上它的价值。 28 | max函数的巧妙在于直接决定放i与否可以取得最大值。 29 | */ 30 | } 31 | else f[i][j] = f[i-1][j];//这个物品的体积超过了我们目前枚举的背包容积j,因此不放入它,保持上次的原样 32 | cout << f[n][v] << endl;//这里求得的f[n][v]即为所求放入背包内的物品的最大价值和。 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /图论/最短路/SPFA.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | #define UINF 0xffffffff 7 | struct Edge { 8 | int to; 9 | int w; 10 | Edge(int _to,int _w):to(_to),w(_w){} 11 | }; 12 | vector g[10005];//数组模拟邻接表 13 | unsigned int dis[10005]; 14 | bool inqueue[10005]; 15 | int main() { 16 | int N,M,S; 17 | scanf("%d%d%d",&N,&M,&S); 18 | for (int i=0;i q; 26 | q.push(S); 27 | while(!q.empty()) { 28 | int curr = q.front(); 29 | q.pop(); 30 | inqueue[curr] = false; 31 | for (int i=0;i 2 | #include 3 | #include 4 | using namespace std; 5 | struct Edge{ 6 | int u,v,w; 7 | Edge(int _u,int _v,int _w):u(_u),v(_v),w(_w){} 8 | Edge(){} 9 | }; 10 | Edge e[200005]; 11 | int family[5005];//记录这个节点的根节点 12 | int find(int member){ 13 | if (family[member] == member) return member; 14 | else { 15 | family[member] = find(family[member]);//记忆化 16 | return family[member]; 17 | } 18 | } 19 | bool comp(const Edge &a,const Edge &b){ 20 | if (a.w < b.w) return true; 21 | return false; 22 | } 23 | int main() { 24 | int N,M; 25 | cin >> N >> M; 26 | for (int i=1;i<=N;i++) family[i] = i;//初始化并查集 27 | for (int i=0;i> X >> Y >> Z; 30 | e[i] = Edge(X,Y,Z); 31 | } 32 | sort(e,e+M,comp); 33 | int k = 0;//记录连起来的边数 34 | int tot = 0;//已经连起来的边权 35 | for (int i=0;i 2 | #include 3 | using std::min; 4 | int head[100005]; 5 | int next[200005]; 6 | int to[200005]; 7 | int dfn[100005]; 8 | int low[100005]; 9 | bool cut[100005]; 10 | int edgecnt = 0; 11 | int dfscnt = 0; 12 | int n,m; 13 | void addedge(int u,int v) { 14 | edgecnt ++; 15 | next[edgecnt] = head[u]; 16 | head[u] = edgecnt; 17 | to[edgecnt] = v; 18 | } 19 | void tarjan(int u,int r) { 20 | int rc = 0; 21 | dfn[u] = low[u] = ++dfscnt; 22 | for (int edge=head[u];edge!=0;edge=next[edge]) { 23 | int v = to[edge]; 24 | if (!dfn[v]) { 25 | tarjan(v,r); 26 | low[u]=min(low[u],low[v]); 27 | if (low[v] >= dfn[u] && u != r) cut[u] = true; 28 | if (u == r) rc++; 29 | } 30 | low[u] = min(low[u],dfn[v]); 31 | } 32 | if (u == r && rc >= 2) cut[r] = true; 33 | } 34 | int main() { 35 | scanf("%d%d",&n,&m); 36 | for (int i=1;i<=m;i++) { 37 | int u,v; 38 | scanf("%d%d",&u,&v); 39 | addedge(u,v); 40 | addedge(v,u); 41 | } 42 | for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,i); 43 | int ans = 0; 44 | for (int i=1;i<=n;i++) if (cut[i]) ans++; 45 | printf("%d\n",ans); 46 | for (int i=1;i<=n;i++) if (cut[i]) printf("%d ",i); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /图论/最小生成树/Prim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | struct Edge{ 7 | int to; 8 | int weight; 9 | Edge(int _to,int _weight):to(_to),weight(_weight){} 10 | }; 11 | vector g[5005]; 12 | int main() { 13 | ios::sync_with_stdio(false); 14 | int N,M; 15 | cin >> N >> M; 16 | for (int i=0;i> X >> Y >> Z; 19 | g[X].push_back(Edge(Y,Z)); 20 | g[Y].push_back(Edge(X,Z)); 21 | //变长数组模拟邻接表 22 | 23 | } 24 | int dis[5005]; 25 | bool flag[5005]={0}; 26 | memset(dis,0x7f,sizeof(dis)); 27 | int k = 1;//从1号点开始扩展 28 | int tot = 0; 29 | while(k != -1){ 30 | flag[k] = true; 31 | for (int i=0;i 2 | using namespace std; 3 | vector g[1005]; 4 | int pre[1005],nxt[1005]; 5 | bool visl[1005],visr[1005]; 6 | bool dfs(int u) { 7 | visl[u] = true; 8 | for (auto v:g[u]) { 9 | if (visr[v]) continue; 10 | visr[v] = true; 11 | if (pre[v] == -1 || dfs(pre[v])) { 12 | pre[v] = u; 13 | nxt[u] = v; 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | int r,c,n; 20 | void work() { 21 | int match = 0; 22 | memset(pre,-1,sizeof(pre)); 23 | memset(nxt,-1,sizeof(nxt)); 24 | memset(visl,false,sizeof(visl)); 25 | for (int i=1;i<=r;i++) { 26 | if (!g[i].size()) continue; 27 | memset(visr,0,sizeof(visr)); 28 | match += dfs(i); 29 | } 30 | memset(visl,false,sizeof(visl)); 31 | memset(visr,false,sizeof(visr)); 32 | for (int i=1;i<=r;i++) if (nxt[i] == -1) dfs(i); 33 | printf("%d",match); 34 | for (int i=1;i<=r;i++) if (!visl[i]) printf(" r%d",i); 35 | for (int i=1;i<=c;i++) if (visr[i]) printf(" c%d",i); 36 | printf("\n"); 37 | } 38 | int main() { 39 | while (scanf("%d%d%d",&r,&c,&n) == 3 && n) { 40 | for (int i=1;i<=r;i++) g[i].clear(); 41 | for (int i=0;i 2 | using namespace std; 3 | vector g[2000005]; 4 | bool vis[2000005]; 5 | int dfn[2000005],low[2000005],root[2000005]; 6 | int rootcnt; 7 | int timestamp; 8 | stack s; 9 | void tarjan(int u) { 10 | dfn[u] = low[u] = ++timestamp; 11 | vis[u] = true; 12 | s.push(u); 13 | for (auto v:g[u]) { 14 | if (!dfn[v]) { 15 | tarjan(v); 16 | low[u] = min(low[u],low[v]); 17 | } 18 | else { 19 | if (vis[v]) low[u] = min(low[u],dfn[v]); 20 | } 21 | } 22 | if (dfn[u] == low[u]) { 23 | rootcnt ++; 24 | while (!s.empty()) { 25 | int v = s.top(); 26 | s.pop(); 27 | root[v] = rootcnt; 28 | vis[v] = false; 29 | if (v == u) break; 30 | } 31 | } 32 | } 33 | int main() { 34 | int n,m; 35 | scanf("%d%d",&n,&m); 36 | while (m --) { 37 | int i,a,j,b; 38 | scanf("%d%d%d%d",&i,&a,&j,&b); 39 | g[i+n*(a&1)].push_back(j+n*(b^1)); 40 | g[j+n*(b&1)].push_back(i+n*(a^1)); 41 | } 42 | for (int i=1;i<=2*n;i++) if (!dfn[i]) tarjan(i); 43 | bool ans = true; 44 | for (int i=1;i<=n && ans;i++) if (root[i] == root[i+n]) ans = false; 45 | if (ans) { 46 | printf("POSSIBLE\n"); 47 | for (int i=1;i<=n;i++) printf("%d ",root[i] g[100005],g2[100005];//反向图 正向图 3 | int deg[100005],seq[100005]; 4 | void topo_sort() { 5 | queue q; 6 | for (int i=1;i<=n;i++) if (deg[i] == 0) { 7 | q.push(i); 8 | g[0].push_back(i); 9 | g2[i].push_back(0); 10 | } 11 | int cnt = 0; 12 | while (!q.empty()) { 13 | int u = q.front(); 14 | q.pop(); 15 | seq[++cnt] = u; 16 | for (auto v:g[u]) { 17 | deg[v] --; 18 | if (deg[v] == 0) q.push(v); 19 | } 20 | } 21 | } 22 | int f[100005][18],dep[100005]; 23 | int LCA(int u,int v) { 24 | if (dep[u] > dep[v]) swap(u,v); 25 | int diff = dep[v] - dep[u]; 26 | for (int i=0,bin=1;diff;i++,bin<<=1) if (diff & bin) { 27 | v = f[v][i]; 28 | diff -= bin; 29 | } 30 | if (u == v) return u; 31 | int m = 0; 32 | while ((1 << m) < dep[u]) m ++; 33 | for (int i=m;i>=0;i--) if (f[u][i] != f[v][i]) { 34 | u = f[u][i]; 35 | v = f[v][i]; 36 | } 37 | return f[u][0]; 38 | } 39 | void build() { 40 | topo_sort(); 41 | dep[0] = 1; 42 | for (int i=1;i<=n;i++) { 43 | int up = -1; 44 | int u = seq[i]; 45 | for (auto v:g2[u]) { 46 | if (up == -1) up = v; 47 | else up = LCA(up,v); 48 | } 49 | f[u][0] = up; 50 | dep[u] = dep[up]+1; 51 | for (int i=1,bin=1;bin<=dep[u];i++,bin<<=1) f[u][i] = f[f[u][i-1]][i-1]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /数据结构/rmq-ST算法.cpp: -------------------------------------------------------------------------------- 1 | //http://noalgo.info/489.html 2 | //仅用于求出区间内最小值 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | int a[10005]; 8 | int st[10005][30]; 9 | void initRMQ(int maxn) { 10 | for (int i=0;i v) swap(u,v);//非常重要!!!特别是在做LCA的时候 21 | int k = log(v-u+1)/log(2); 22 | //printf("RMQ(%d,%d)=min(st[%d][%d],st[%d,%d])\n",u,v,u,k,v-int(pow(2,k))+1,k); 23 | return min(st[u][k],st[v-int(pow(2,k))+1][k]); 24 | } 25 | int main() { 26 | int n; 27 | scanf("%d",&n); 28 | for (int i=0;i 3 | using namespace std; 4 | struct DATA { 5 | int v; 6 | int pos; 7 | friend bool operator < (const DATA &a,const DATA &b) { 8 | return a.v < b.v; 9 | } 10 | }d[5005]; 11 | int r[5005]; 12 | int tr[5005]; 13 | int n; 14 | inline int lowbit(int x) { 15 | return x & (-x); 16 | } 17 | inline long long sum(int x) { 18 | long long ret = 0; 19 | for (int i=x;i>=1;i-=lowbit(i)) ret += tr[i]; 20 | return ret; 21 | } 22 | inline void add(int x,int d) { 23 | for (int i=x;i<=n;i+=lowbit(i)) tr[i] += d; 24 | } 25 | int main() { 26 | while (scanf("%d",&n) == 1) { 27 | memset(tr,0,sizeof(tr)); 28 | for (int i=1;i<=n;i++) { 29 | scanf("%d",&d[i].v); 30 | d[i].pos = i; 31 | } 32 | sort(d+1,d+1+n); 33 | int rank = 0; 34 | for (int i=1;i<=n;i++) { 35 | if (i == 1 || d[i].v != d[i-1].v) rank ++; 36 | r[d[i].pos] = rank; 37 | } 38 | long long cnt = 0;//这里所求即为未循环前的逆序对数 39 | for (int i=n;i>=1;i--) { 40 | cnt += sum(r[i]-1); 41 | add(r[i],1); 42 | } 43 | long long ans = cnt; 44 | for (int i=1;i<=n;i++) { 45 | cnt = cnt - 2*(r[i]-1) + n - 1;//rank从1开始,所以-1 46 | //将第一个数移动到最后,则逆序对数会减少r[i]-1个 47 | //同时,逆序对数会增加n-r[i]个 48 | //最后得cnt = cnt - 2*(r[i]-1) + n - 1; 49 | ans = min(ans,cnt); 50 | } 51 | printf("%lld\n",ans); 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /数学/Miller_Rabin素数测试.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | long long mul(long long a,long long b,long long mod){ 4 | long long ret=0; 5 | while(b) { 6 | if(b & 1) { 7 | ret += a; 8 | ret %= mod; 9 | } 10 | a <<= 1; 11 | a %= mod; 12 | b>>=1; 13 | } 14 | return ret; 15 | } 16 | long long pow(long long a,long long b,long long mod) { 17 | long long ret=1; 18 | while(b) { 19 | if(b & 1) ret = mul(ret,a,mod); 20 | a = mul(a,a,mod); 21 | b >>= 1; 22 | } 23 | return ret; 24 | } 25 | bool check(long long a,long long n){ 26 | long long x=n - 1; 27 | int t=0; 28 | while((x & 1) == 0) { 29 | x >>= 1; 30 | t++; 31 | } 32 | x = pow(a,x,n); 33 | long long y; 34 | for(int i=1;i<=t;i++) { 35 | y = mul(x,x,n); 36 | if(y == 1 && x != 1 && x != n - 1) return true; 37 | x=y; 38 | } 39 | if(y != 1) return true; 40 | return false; 41 | } 42 | bool Is_Prime(long long n) { 43 | if(n == 2) return true; 44 | if(n == 1 || !(n & 1)) return false; 45 | const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37}; 46 | for(int i = 0; i < 12; i++) { 47 | if (arr[i] >= n) break; 48 | if(check(arr[i], n)) return false; 49 | } 50 | return true; 51 | } 52 | int main() { 53 | int n,m; 54 | scanf("%d%d",&n,&m); 55 | while (m --) { 56 | long long x; 57 | scanf("%lld",&x); 58 | if (Is_Prime(x)) printf("Yes\n"); 59 | else printf("No\n"); 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /数据结构/堆(手写).cpp: -------------------------------------------------------------------------------- 1 | //Luogu P3378:https://www.luogu.org/problemnew/show/P3378 2 | #include 3 | using std::swap; 4 | class pq { 5 | public: 6 | void init() { 7 | size = 0; 8 | } 9 | void push(int x) { 10 | arr[++size] = x; 11 | shift_up(size); 12 | } 13 | int top() { 14 | return arr[1]; 15 | } 16 | void pop() { 17 | swap(arr[1],arr[size]); 18 | size --; 19 | shift_down(1); 20 | } 21 | private: 22 | int arr[1000005]; 23 | int size; 24 | void shift_up(int node) { 25 | while ( (node >> 1) >= 1) { 26 | int T = node >> 1;//父节点 27 | if (arr[node] < arr[T]) swap(arr[node],arr[T]);//小根堆,如果自己比父节点小,就交换 28 | else break; 29 | node = T; 30 | } 31 | } 32 | void shift_down(int node) { 33 | while ( (node << 1) <= size) { 34 | int T = node << 1;//它的左子节点 35 | if (T+1 <= size && arr[T+1] < arr[T]) T = T+1;//右子节点存在且更小时,选择右子节点 36 | if (arr[node] > arr[T]) swap(arr[node],arr[T]);//小根堆,如果自己比子节点大,就交换 37 | else break; 38 | node = T; 39 | } 40 | } 41 | }q; 42 | int main() { 43 | q.init(); 44 | int n; 45 | scanf("%d",&n); 46 | while(n--) { 47 | int o; 48 | scanf("%d",&o); 49 | switch(o) { 50 | case 1: 51 | int x; 52 | scanf("%d",&x); 53 | q.push(x); 54 | break; 55 | case 2: 56 | printf("%d\n",q.top()); 57 | break; 58 | case 3: 59 | q.pop(); 60 | break; 61 | } 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /字符串/AC自动机.cpp: -------------------------------------------------------------------------------- 1 | //给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。 2 | #include 3 | using namespace std; 4 | struct node { 5 | int cnt; 6 | int next;//匹配不上时走的节点 7 | int ch[26]; 8 | }tr[1000005]; 9 | int ncnt = 0; 10 | void insert(char *s) { 11 | int cur = 0; 12 | int len = strlen(s); 13 | for (int i=0;i q;//一定要广搜 22 | for (int i=0;i<26;i++) { 23 | if (tr[0].ch[i]) { 24 | tr[tr[0].ch[i]].next = 0; 25 | q.push(tr[0].ch[i]); 26 | } 27 | } 28 | while (!q.empty()) { 29 | int u = q.front(); 30 | q.pop(); 31 | for (int i=0;i<26;i++) { 32 | int &v = tr[u].ch[i]; 33 | if (v) { 34 | tr[v].next = tr[tr[u].next].ch[i]; 35 | q.push(v); 36 | } 37 | else { 38 | v = tr[tr[u].next].ch[i]; 39 | } 40 | } 41 | } 42 | } 43 | int getans(char *s) { 44 | int len = strlen(s); 45 | int cur = 0; 46 | int ans = 0; 47 | for (int i=0;i 3 | int n,m,s; 4 | int f[500005]; 5 | int ehead[500005]; 6 | int qhead[500005]; 7 | struct Edge { 8 | int v; 9 | int next; 10 | }e[1000005]; 11 | int ecnt = 0; 12 | struct Query { 13 | int v; 14 | int next; 15 | }q[1000005]; 16 | int qcnt = 0; 17 | inline void AddEdge(int u,int v) { 18 | e[ecnt].v = v; 19 | e[ecnt].next = ehead[u]; 20 | ehead[u] = ecnt; 21 | ecnt ++; 22 | } 23 | inline void AddQuery(int u,int v) { 24 | q[qcnt].v = v; 25 | q[qcnt].next = qhead[u]; 26 | qhead[u] = qcnt; 27 | qcnt ++; 28 | } 29 | inline int find(int x) { 30 | if (f[x] != x) f[x] = find(f[x]); 31 | return f[x]; 32 | } 33 | inline void uni(int u,int v) { 34 | f[find(u)] = find(v); 35 | } 36 | int ans[500005]; 37 | bool vis[500005]; 38 | void tarjan(int node) { 39 | vis[node] = true; 40 | for (int i=ehead[node];i != -1;i=e[i].next) { 41 | if (!vis[e[i].v]) { 42 | tarjan(e[i].v); 43 | uni(e[i].v,node); 44 | } 45 | } 46 | for (int i=qhead[node];i != -1;i=q[i].next) { 47 | if (vis[q[i].v]) ans[i>>1] = find(q[i].v); 48 | } 49 | } 50 | int main() { 51 | memset(ehead,-1,sizeof(ehead)); 52 | memset(qhead,-1,sizeof(qhead)); 53 | scanf("%d%d%d",&n,&m,&s); 54 | for (int i=1;i<=n;i++) f[i] = i; 55 | for (int i=1;i 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | bool NotPrime[50005]; 8 | vector Prime; 9 | void GetPrime(long long x) { 10 | memset(NotPrime,false,sizeof(NotPrime)); 11 | NotPrime[1] = true; 12 | for (long long i=2;i<=x;i++) { 13 | if (!NotPrime[i]) Prime.push_back(i); 14 | for (unsigned long j=0;j x) break; 17 | NotPrime[i*p] = true; 18 | if (i % p == 0) break; 19 | } 20 | } 21 | } 22 | long long getphi(long long x) { 23 | long long ret = x; 24 | 25 | for (unsigned long i=0;i 1) { 35 | ret /= x; 36 | ret *= (x - 1); 37 | } 38 | return ret; 39 | } 40 | long long qpow(long long a,long long b,long long mod) { 41 | long long base = a; 42 | long long ret = 1; 43 | while (b) { 44 | if (b & 1) { 45 | ret *= base; 46 | ret %= mod; 47 | } 48 | base *= base; 49 | base %= mod; 50 | b >>= 1; 51 | } 52 | return ret % mod; 53 | } 54 | char s[1000005]; 55 | int main() { 56 | GetPrime(50000); 57 | long long a,c; 58 | while (cin >> a >> s >> c) { 59 | long long phi = getphi(c); 60 | int len = strlen(s); 61 | long long b = 0; 62 | for (int i=0;i 3 | using namespace std; 4 | struct p { 5 | int u; 6 | int dis; 7 | friend bool operator < (const p &a,const p &b) { 8 | return a.dis > b.dis; 9 | } 10 | p(int _u,int _dis) { 11 | u = _u; 12 | dis = _dis; 13 | } 14 | }; 15 | struct edge { 16 | int v,w; 17 | int next; 18 | }e[200005]; 19 | int head[100005]; 20 | int ecnt; 21 | void AddEdge(int u,int v,int w) { 22 | e[ecnt].v = v; 23 | e[ecnt].w = w; 24 | e[ecnt].next = head[u]; 25 | head[u] = ecnt; 26 | ecnt ++; 27 | } 28 | int read() { 29 | int ret = 0; 30 | int f = 1; 31 | char c = getchar(); 32 | while (!(c >= '0' && c <= '9')) { 33 | if (c == '-') f = -f; 34 | c = getchar(); 35 | } 36 | while (c >= '0' && c <= '9') { 37 | ret *= 10; 38 | ret += c - '0'; 39 | c = getchar(); 40 | } 41 | return ret * f; 42 | } 43 | int dis[100005]; 44 | void spfa(int s) { 45 | memset(dis,0x3f,sizeof(dis)); 46 | dis[s] = 0; 47 | priority_queue

q; 48 | q.push(p(s,0)); 49 | while (!q.empty()) { 50 | p cur = q.top(); 51 | q.pop(); 52 | int u = cur.u; 53 | if (cur.dis > dis[u]) continue; 54 | for (int i=head[u];i != -1;i=e[i].next) { 55 | int v = e[i].v; 56 | int w = e[i].w; 57 | if (dis[u] + w < dis[v]) { 58 | dis[v] = dis[u] + w; 59 | q.push(p(v,dis[v])); 60 | } 61 | } 62 | } 63 | } 64 | int main() { 65 | memset(head,-1,sizeof(head)); 66 | ecnt = 0; 67 | int n,m,s; 68 | scanf("%d%d%d",&n,&m,&s); 69 | while (m--) { 70 | int u,v,w; 71 | scanf("%d%d%d",&u,&v,&w); 72 | AddEdge(u,v,w); 73 | } 74 | spfa(s); 75 | for (int i=1;i<=n;i++) { 76 | if (i != 1) printf(" "); 77 | printf("%d",dis[i]); 78 | } 79 | printf("\n"); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /数学/线性基.cpp: -------------------------------------------------------------------------------- 1 | //给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大。 2 | #include 3 | using namespace std; 4 | struct LB { 5 | long long r[63]; 6 | LB() { 7 | memset(r,0,sizeof(r)); 8 | } 9 | LB(const LB &b) { 10 | for (int i=0;i<63;i++) r[i] = b.r[i]; 11 | } 12 | bool insert(long long x) { 13 | for (int i=62;i>=0;i--) { 14 | if ((x >> i) & 1) { 15 | if (r[i] == 0) { 16 | r[i] = x; 17 | return true; 18 | } 19 | else x ^= r[i]; 20 | } 21 | } 22 | return false; 23 | } 24 | bool check(long long x) { 25 | for (int i=62;i>=0;i--) { 26 | if ((x >> i) & 1) { 27 | if (r[i] == 0) return false; 28 | x ^= r[i]; 29 | } 30 | } 31 | return true; 32 | } 33 | long long query_max(long long ret = 0) {//自定义初始值 34 | for (int i=62;i>=0;i--) ret = max(ret,ret^r[i]); 35 | return ret; 36 | } 37 | void merge(const LB &b) { 38 | for (int i=0;i<=62;i++) insert(b.r[i]); 39 | } 40 | static LB intersect(const LB &a,const LB &b) { 41 | LB all,d,ret; 42 | for (int i=63;i>=0;i--) { 43 | all.r[i] = a.r[i]; 44 | d.r[i] = 1 << i; 45 | } 46 | for (int i=63;i>=0;i--) if (b.r[i]) { 47 | long long v = b.r[i],k = 0; 48 | bool flag = true; 49 | for (int j=63;j>=0;j--) if ((v >> j) & 1) { 50 | if (all.r[j]) { v ^= all.r[j]; k ^= d.r[j];} 51 | else { flag = false; all.r[j] = v; d.r[j] = k; break; } 52 | } 53 | if (flag) { 54 | long long tmp = 0; 55 | for (int j=63;j>=0;j--) if ((k >> j) & 1) tmp ^= a.r[j]; 56 | ret.insert(tmp); 57 | } 58 | } 59 | return ret; 60 | } 61 | }; 62 | int main() { 63 | LB A; 64 | int n; 65 | scanf("%d",&n); 66 | while (n --) { 67 | long long x; 68 | scanf("%lld",&x); 69 | A.insert(x); 70 | } 71 | cout << A.query_max() << endl; 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /计算几何/二维凸包模板.cpp: -------------------------------------------------------------------------------- 1 | //HDU 1392 2 | #include 3 | using namespace std; 4 | #define PDD pair 5 | #define y first 6 | #define x second 7 | int n; 8 | PDD p[105]; 9 | template 10 | class mystack : public stack { 11 | public: 12 | T sec() { 13 | T tmp = this->top(); 14 | this->pop(); 15 | T sec = this->top(); 16 | this->push(tmp); 17 | return sec; 18 | } 19 | }; 20 | inline bool judge(const PDD &e,const PDD &c,const PDD &s) { 21 | return (e.x - s.x) * (c.y - s.y) - (c.x - s.x) * (e.y - s.y) >= 0; 22 | } 23 | void graham(vector &res) { 24 | sort(p,p+n); 25 | mystack s; 26 | for (int i=0;i 2) { 28 | for (int i=2;i=2 && judge(p[i],s.top(),s.sec())) s.pop(); 30 | s.push(p[i]); 31 | } 32 | int len = s.size(); 33 | s.push(p[n-2]); 34 | for (int i=n-3;i>=0;i--) { 35 | while ((int)s.size() > len && judge(p[i],s.top(),s.sec())) s.pop(); 36 | s.push(p[i]); 37 | } 38 | } 39 | else s.push(p[0]); 40 | res.clear(); 41 | while (!s.empty()) { 42 | res.push_back(s.top()); 43 | s.pop(); 44 | } 45 | } 46 | inline double dis(const PDD &a,const PDD &b) { 47 | return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); 48 | } 49 | int main() { 50 | while (scanf("%d",&n) == 1) { 51 | if (n == 0) break; 52 | for (int i=0;i res; 54 | graham(res); 55 | double ans = 0; 56 | if (res.size() > 2) { 57 | if (res.size() > 3) 58 | for (int i=0;i<(int)res.size()-1;i++) ans += dis(res[i],res[i+1]); 59 | else ans += dis(res[0],res[1]); 60 | } 61 | printf("%0.2lf\n",ans); 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /数学/多项式.cpp: -------------------------------------------------------------------------------- 1 | const double pi = acos((double)-1); 2 | const int maxn = 1<<22;//2e6 3 | namespace fft { 4 | complex omega[maxn]; 5 | void init(int n) { 6 | for (int i=0;i(cos(2*pi*i/n),sin(2*pi*i/n)); 8 | } 9 | } 10 | void transform(complex *a,int n,bool inv) { 11 | int k = 0; 12 | while ((1 << k) < n) k ++; 13 | for (int i=0;i t = (inv?conj(omega[n/l*i]):omega[n/l*i]) * p[m+i]; 23 | p[m+i] = p[i] - t; 24 | p[i] += t; 25 | } 26 | } 27 | } 28 | } 29 | void dft(complex *a,int n) { 30 | transform(a,n,false); 31 | } 32 | void idft(complex *a,int n) { 33 | transform(a,n,true); 34 | for (int i=0;i { 38 | friend poly operator * (const poly &a,const poly &b) { 39 | int n = 1; 40 | while (n < a.size() + b.size()) n <<= 1; 41 | static complex c1[maxn],c2[maxn]; 42 | for (int i=0;i(a[i],0); 43 | for (int i=a.size();i(0,0); 44 | for (int i=0;i(b[i],0); 45 | for (int i=b.size();i(0,0); 46 | fft::init(n); 47 | fft::dft(c1,n); 48 | fft::dft(c2,n); 49 | for (int i=0;i 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | int n,m; 8 | int st[301][301][9][9]; 9 | int pow2(int x) { 10 | return 1 << x;//相当于计算2的x次方,使用位运算 11 | } 12 | void init() { 13 | //st[x][y][0][0]已经预先填充 14 | for (int i=0;i<=log2(n);i++) 15 | for (int j=0;j<=log2(m);j++) { 16 | if (i == 0 && j == 0) continue; 17 | for (int x=1;x<=n;x++) for (int y=1;y<=m;y++) { 18 | int rangex = x + pow2(i) - 1; 19 | int rangey = y + pow2(j) - 1; 20 | if (rangex > n || rangey > m) continue; 21 | if (i == 0) { 22 | st[x][y][i][j] = max( st[x][ y ][i][j-1], 23 | st[x][y+pow2(j-1) ][i][j-1]); 24 | } 25 | else { 26 | st[x][y][i][j] = max( st[ x ][y][i-1][j], 27 | st[x+pow2(i-1) ][y][i-1][j]); 28 | } 29 | } 30 | } 31 | } 32 | int query_max(int x1,int y1,int x2,int y2) { 33 | int k1 = log2(x2-x1+1); 34 | int k2 = log2(y2-y1+1); 35 | return max( 36 | max( 37 | st[ x1 ][y1][k1][k2], 38 | st[x2-pow2(k1)+1][y1][k1][k2] 39 | ), 40 | max( 41 | st[x1][y2-pow2(k2)+1][k1][k2], 42 | st[x2-pow2(k1)+1][y2-pow2(k2)+1][k1][k2] 43 | ) 44 | ); 45 | } 46 | int main() { 47 | while (scanf("%d%d",&n,&m) == 2) { 48 | for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { 49 | scanf("%d",&st[i][j][0][0]); 50 | } 51 | init(); 52 | int q; 53 | scanf("%d",&q); 54 | while (q --) { 55 | int r1,c1,r2,c2; 56 | scanf("%d%d%d%d",&r1,&c1,&r2,&c2); 57 | int max_value = query_max(r1,c1,r2,c2); 58 | printf("%d ",max_value); 59 | if (max_value == max(max(st[r1][c1][0][0],st[r1][c2][0][0]),max(st[r2][c1][0][0],st[r2][c2][0][0]))) puts("yes"); 60 | else puts("no"); 61 | } 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /图论/桥.cpp: -------------------------------------------------------------------------------- 1 | //http://poj.org/problem?id=3177 2 | //给一张无向图,问需要加多少条边,使得图没有桥 3 | //求边双,然后统计度数为1的节点个数,每次选两个点连起来,就是答案 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | const int maxn = 10005; 9 | const int maxm = 20005; 10 | struct DATA { 11 | int v,next; 12 | }e[20005]; 13 | int ecnt; 14 | int head[maxn]; 15 | void addedge(int u,int v) { 16 | e[ecnt].v = v; 17 | e[ecnt].next = head[u]; 18 | head[u] = ecnt; 19 | ecnt ++; 20 | } 21 | int dfn[maxn],low[maxn]; 22 | int ts; 23 | bool br[maxm]; 24 | void tarjan(int u,int r) { 25 | dfn[u] = low[u] = ++ts; 26 | for (int i=head[u];~i;i=e[i].next) { 27 | int v = e[i].v; 28 | if (v == r) continue; 29 | if (!dfn[v]) { 30 | tarjan(v,u); 31 | if (low[v] > dfn[u]) { 32 | br[ i ] = true; 33 | br[i^1] = true; 34 | } 35 | low[u] = min(low[u],low[v]); 36 | } 37 | else low[u] = min(low[u],dfn[v]); 38 | } 39 | } 40 | int rt[maxn],subg; 41 | int deg[maxn]; 42 | void dfs(int u) { 43 | rt[u] = subg; 44 | for (int i=head[u];~i;i=e[i].next) { 45 | if (br[i]) continue; 46 | int v = e[i].v; 47 | if (!rt[v]) dfs(v); 48 | } 49 | } 50 | int main() { 51 | memset(head,-1,sizeof(head)); 52 | int f,r; 53 | scanf("%d%d",&f,&r); 54 | for (int i=0;i 3 | using namespace std; 4 | int head[500005]; 5 | struct Edge { 6 | int v; 7 | int next; 8 | }e[1000005]; 9 | int ecnt = 0; 10 | int n,m,s; 11 | inline void AddEdge(int u,int v) { 12 | e[ecnt].v = v; 13 | e[ecnt].next = head[u]; 14 | head[u] = ecnt; 15 | ecnt ++; 16 | } 17 | inline int read() { 18 | int f = 1; 19 | int ret = 0; 20 | char c = getchar(); 21 | while (!(c >= '0' && c <= '9')) { 22 | if (c == '-') f = -f; 23 | c = getchar(); 24 | } 25 | while (c >= '0' && c <= '9') { 26 | ret *= 10; 27 | ret += c - '0'; 28 | c = getchar(); 29 | } 30 | return ret * f; 31 | } 32 | int vis[500005]; 33 | int up[500005][25]; 34 | int dep[500005]; 35 | void dfs(int u) { 36 | vis[u] = true; 37 | for (int i=1,len=1;len<=dep[u];i++,len <<= 1) up[u][i] = up[up[u][i-1]][i-1]; 38 | for (int i=head[u];i != -1;i = e[i].next) { 39 | if (!vis[e[i].v]) { 40 | dep[e[i].v] = dep[u] + 1; 41 | up[e[i].v][0] = u; 42 | dfs(e[i].v); 43 | } 44 | } 45 | } 46 | int query(int u,int v) { 47 | //u <= v,v更深 48 | if (dep[u] > dep[v]) swap(u,v); 49 | int diff = dep[v] - dep[u]; 50 | for (int i=0,two=1;diff != 0;two <<= 1,i++) { 51 | if (diff & two) { 52 | v = up[v][i]; 53 | diff -= two; 54 | } 55 | } 56 | if (u == v) return u; 57 | for (int i=log(dep[u])/log(2);i>=0;i--) { 58 | if (up[u][i] != up[v][i]) { 59 | u = up[u][i]; 60 | v = up[v][i]; 61 | } 62 | } 63 | return up[u][0]; 64 | } 65 | int main() { 66 | memset(head,-1,sizeof(head)); 67 | n = read(); 68 | m = read(); 69 | s = read(); 70 | for (int i=1;i 3 | #include 4 | #include 5 | using namespace std; 6 | const int maxn = 10005; 7 | const int maxe = 50005; 8 | int dfn[maxn],low[maxn],rt[maxn],sz[maxn],ts,scc; 9 | bool vis[maxn]; 10 | stack s; 11 | int head[maxn]; 12 | struct Edge { 13 | int v,next; 14 | }e[maxe]; 15 | int ecnt; 16 | void addedge(int u,int v) { 17 | e[ecnt].v = v; 18 | e[ecnt].next = head[u]; 19 | head[u] = ecnt; 20 | ecnt ++; 21 | } 22 | void tarjan(int u) { 23 | dfn[u] = low[u] = ++ts; 24 | vis[u] = true; 25 | s.push(u); 26 | for (int i=head[u];~i;i=e[i].next) { 27 | int v = e[i].v; 28 | if (!dfn[v]) { 29 | tarjan(v); 30 | low[u] = min(low[u],low[v]); 31 | } 32 | else if (vis[v]) low[u] = min(low[u],dfn[v]); 33 | } 34 | if (dfn[u] == low[u]) { 35 | scc ++; 36 | while (!s.empty()) { 37 | int v = s.top(); 38 | s.pop(); 39 | rt[v] = scc; 40 | sz[scc] ++; 41 | vis[v] = false; 42 | if (v == u) break; 43 | } 44 | } 45 | } 46 | int outdeg[maxn]; 47 | int main() { 48 | int n,m; 49 | while (scanf("%d%d",&n,&m) == 2) { 50 | memset(head,-1,sizeof(head)); 51 | ecnt = 0; 52 | ts = 0; 53 | scc = 0; 54 | for (int i=1;i<=n;i++) dfn[i] = low[i] = rt[i] = sz[i] = 0; 55 | for (int i=0;i 0) printf("%d\n",sz[ans]); 76 | else printf("0\n"); 77 | } 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /图论/网络流/最大流dinic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int INF = 0x3f3f3f3f; 4 | struct Edge{ 5 | int f,v,next; 6 | }e[200005]; 7 | int ecnt = 0;//因为采用了一个邻接表奇偶存两条边的方法,所以必须从偶数开始 8 | int head[10005]; 9 | void _AddEdge(int u,int v,int c) { 10 | e[ecnt].v = v; 11 | e[ecnt].f = c; 12 | e[ecnt].next = head[u]; 13 | head[u] = ecnt; 14 | ecnt ++; 15 | } 16 | void AddEdge(int u,int v,int c) { 17 | _AddEdge(u,v,c); 18 | _AddEdge(v,u,0); 19 | } 20 | int dis[10005]; 21 | bool bfs(int s,int t) {//划分层次,同时判断是否可到达 22 | memset(dis,0x3f,sizeof(dis)); 23 | dis[s] = 1; 24 | queue q; 25 | q.push(s); 26 | while(!q.empty()) { 27 | int u = q.front(); 28 | q.pop(); 29 | if (u == t) return 1; 30 | for (int i=head[u];i!=-1;i = e[i].next) { 31 | int v = e[i].v; 32 | if (e[i].f != 0 && dis[v] == INF) { 33 | dis[v] = dis[u] + 1; 34 | q.push(v); 35 | } 36 | } 37 | } 38 | return dis[t] != INF; 39 | } 40 | 41 | int dfs(int u,int t,int curflow) {//curflow=>当前可增广的最大流量 42 | if (curflow == 0 || u == t) return curflow; 43 | if (dis[u] >= dis[t]) return 0; 44 | int ret = 0; 45 | for (int i=head[u];i!=-1 && ret < curflow;i=e[i].next) { 46 | int v = e[i].v; 47 | int f = e[i].f; 48 | if (dis[v] == dis[u] + 1 && f != 0) { 49 | int pushflow = min(curflow-ret,f); 50 | int chflow = dfs(v,t,pushflow); 51 | if (chflow > 0) { 52 | e[ i ].f -= chflow;//偶数+1,奇数-1,很巧妙的位运算 53 | e[i^1].f += chflow; 54 | ret += chflow; 55 | } 56 | else dis[v] = -1; 57 | } 58 | } 59 | if (ret == 0) dis[u] = -1; 60 | return ret; 61 | } 62 | int dinic(int s,int t) { 63 | int ans = 0; 64 | while(bfs(s,t)) ans += dfs(s,t,INF); 65 | return ans; 66 | } 67 | 68 | int main() { 69 | int n,m,s,t; 70 | scanf("%d%d%d%d",&n,&m,&s,&t); 71 | memset(head,-1,sizeof(head)); 72 | for (int i=0;i G[4005]; 14 | void init(int n) { 15 | V = n; 16 | for (int i = 0; i <= V; ++i)G[i].clear(); 17 | } 18 | void addedge(int from, int to, long long cap, long long cost) { 19 | G[from].push_back(edge(to, cap, cost, G[to].size())); 20 | G[to].push_back(edge(from, 0, -cost, G[from].size() - 1)); 21 | } 22 | long long cal(int s, int t, long long f, long long& flow) { 23 | long long res = 0; 24 | fill(H, H + 1 + V, 0); 25 | while (f) { 26 | priority_queue , vector >, greater > > q; 27 | fill(dis, dis + 1 + V, INF); 28 | dis[s] = 0; q.push(pair(0, s)); 29 | while (!q.empty()) { 30 | pair now = q.top(); q.pop(); 31 | int v = now.second; 32 | if (dis[v] < now.first)continue; 33 | for (int i = 0; i < G[v].size(); ++i) { 34 | edge& e = G[v][i]; 35 | if (e.capacity > 0 && dis[e.to] > dis[v] + e.cost + H[v] - H[e.to]) { 36 | dis[e.to] = dis[v] + e.cost + H[v] - H[e.to]; 37 | PreV[e.to] = v; 38 | PreE[e.to] = i; 39 | q.push(pair(dis[e.to], e.to)); 40 | } 41 | } 42 | } 43 | if (dis[t] == INF)break; 44 | for (int i = 0; i <= V; ++i)H[i] += dis[i]; 45 | long long d = f; 46 | for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity); 47 | f -= d; flow += d; res += d*H[t]; 48 | for (int v = t; v != s; v = PreV[v]) { 49 | edge& e = G[PreV[v]][PreE[v]]; 50 | e.capacity -= d; 51 | G[v][e.rev].capacity += d; 52 | } 53 | } 54 | return res; 55 | } 56 | }MCMF; 57 | -------------------------------------------------------------------------------- /数据结构/线段树/洛谷P3372 【模板】线段树 1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define node ((l+r)|(l!=r)) 5 | #define mid ((l + r) >> 1) 6 | #define lson ((l+mid)|(l!=mid)) 7 | #define rson ((mid+1+r)|(mid+1!=r)) 8 | 9 | struct tree { 10 | long long sum; 11 | long long lazy; 12 | }tr[200005]; 13 | long long a[100005]; 14 | void init(int l,int r) { 15 | if (l == r) { 16 | tr[node].sum = a[l]; 17 | tr[node].lazy = 0; 18 | } 19 | else { 20 | init(l,mid); 21 | init(mid+1,r); 22 | tr[node].sum = tr[lson].sum + tr[rson].sum; 23 | tr[node].lazy = 0; 24 | } 25 | } 26 | void update(int l,int r,int rangeL,int rangeR,long long d) { 27 | //l和r是树的节点 28 | //rangeL和rangeR是要更新的范围 29 | tr[node].sum += (rangeR - rangeL + 1LL) * d; 30 | if (l == rangeL && r == rangeR) { 31 | tr[node].lazy += d; 32 | } 33 | else { 34 | if (rangeL <= mid) update(l,mid,rangeL,min(rangeR,mid),d); 35 | if (rangeR > mid) update(mid+1,r,max(rangeL,mid+1),rangeR,d); 36 | } 37 | } 38 | void push_down(int l,int r) { 39 | if (l != r) { 40 | tr[lson].lazy += tr[node].lazy; 41 | tr[rson].lazy += tr[node].lazy; 42 | tr[lson].sum += (mid-l+1LL) * tr[node].lazy; 43 | tr[rson].sum += (r-(mid+1)+1LL) * tr[node].lazy; 44 | } 45 | tr[node].lazy = 0; 46 | } 47 | long long query(int l,int r,int rangeL,int rangeR) { 48 | if (tr[node].lazy) push_down(l,r); 49 | if (l == rangeL && r == rangeR) return tr[node].sum; 50 | long long ret = 0; 51 | if (rangeL <= mid) ret += query(l,mid,rangeL,min(rangeR,mid)); 52 | if (rangeR > mid) ret += query(mid+1,r,max(rangeL,mid+1),rangeR); 53 | return ret; 54 | } 55 | int main() { 56 | int n,m; 57 | scanf("%d%d",&n,&m); 58 | for (int i=1;i<=n;i++) scanf("%lld",&a[i]); 59 | init(1,n); 60 | for (int i=0;i 3 | using namespace std; 4 | //邻接表{ 5 | //这里采用的是传统的邻接表写法,而非变长数组模拟邻接表 6 | int pre[1000005];//previous,pre[n]代表n节点下的第一条边,也是最后一个插入的边 7 | int nextn[1000005];//nextn[e]代表与e边指向的节点n的上级节点所连的节点中与n相邻的下一条边 8 | int v[1000005];//v[e]代表编号为e的边的指向的节点 9 | int en = 0;//Edge number 10 | inline void AddEdge(int _u,int _v) { 11 | v[en] = _v; 12 | nextn[en] = pre[_u]; 13 | pre[_u] = en; 14 | en++; 15 | } 16 | //} 17 | int n,m,s; 18 | bool vis[1000005]; 19 | int depth[1000005]; 20 | int node[1000005]; 21 | int first[1000005]; 22 | int t = 0; 23 | int st[1000005][20]; 24 | inline int pow2(int n) { 25 | return 1 << n; 26 | } 27 | void init_RMQ(int maxn){ 28 | for (int i=0;i<=maxn;i++) st[i][0] = i; 29 | for (int j=1;pow2(j)<=maxn;j++) { 30 | for (int i=0;i+pow2(j)-1 v) swap(u,v); 39 | int k = log(v-u+1) / log(2); 40 | int l = st[u][k]; 41 | int r = st[v-int(pow2(k))+1][k]; 42 | return depth[l] < depth[r] ? l : r; 43 | } 44 | inline int LCA(int u,int v) { 45 | return node[RMQ(first[u],first[v])]; 46 | } 47 | void DFS(int n,int d) { 48 | node[t] = n; 49 | depth[t] = d; 50 | first[n] = t; 51 | t++; 52 | vis[n] = true; 53 | for (int e=pre[n];e!=-1;e=nextn[e]) { 54 | if (!vis[v[e]]) { 55 | DFS(v[e],d+1); 56 | node[t] = n; 57 | depth[t] = d; 58 | t++; 59 | } 60 | } 61 | } 62 | int main() { 63 | scanf("%d%d%d",&n,&m,&s);//n个节点 64 | memset(nextn,-1,sizeof(nextn)); 65 | memset(pre,-1,sizeof(pre)); 66 | for (int i=1;i 2 | #include 3 | using namespace std; 4 | string sum(string x, string y){//高精加法,要求x,y >= 0,且均属于整数,其他情况请自行修改 5 | string nx; 6 | string ny; 7 | for (int i=x.length()-1;i>=0;i--) nx += x[i]-48; 8 | for (int i=y.length()-1;i>=0;i--) ny += y[i]-48; 9 | //翻转数字 10 | string result; 11 | int add = 0; 12 | bool longer;//为true时x大于y 13 | if (nx.length() > ny.length()) longer = true; else longer = false; 14 | for (int i=0;i 0) result += add; 29 | string final; 30 | bool zeroflag = false;//用于处理多余的0 31 | for (int i=result.length()-1;i>=0;i--){ 32 | if (result[i] == 0) { 33 | if (!zeroflag && i != 0) continue; 34 | } 35 | else zeroflag = true; 36 | final += result[i]+48; 37 | } 38 | return final; 39 | } 40 | string multi(string x, string y){//高精乘法,要求x,y >= 0,且均属于整数,其他情况请自行修改 41 | string nx; 42 | string ny; 43 | for (int i=x.length()-1;i>=0;i--) nx += x[i]-48; 44 | for (int i=y.length()-1;i>=0;i--) ny += y[i]-48; 45 | //翻转数字 46 | string result; 47 | for (int i=0;i=0;j--) t2 += t[j]+48; 58 | string z;//直接以末尾填0的方式乘10 59 | for (int j=1;j<=i;j++) z += "0"; 60 | result = sum(result,t2 + z); 61 | } 62 | return result; 63 | } 64 | int main(){ 65 | string a,b; 66 | cin >> a >> b; 67 | cout << multi(a,b) << endl; 68 | } 69 | -------------------------------------------------------------------------------- /数学/分解质因数求lcm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 通常我们可用a*b/gcd(a,b)求lcm,但许多题目会遇到需要取模的情况,而mod运算只在加、减、乘中满足结合律,因此需要用分解质因数的方法求lcm(最小公倍数) 3 | 该方法很简单,求出每个数的质因数,对于相同的质因数,我们求出每个数的该质因数的个数,然后把这些不同数的相同质因数中各自取数量最大的归为一个集合,把每个最大质因数集合相乘,便得到了lcm。 4 | 具体请百度“分解质因数求最小公倍数”,看数学方法就行 5 | */ 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | struct zys{ 11 | int n;//这个质因数 12 | int s;//这个质因数的数量 13 | zys():n(0),s(0){} 14 | }; 15 | vector l; 16 | void fjzys(int num) { 17 | zys curr; 18 | //短除法,我们在用小的数一遍遍除的时候其实也就把非质数筛掉了,比如2除完不可能再被4整除。 19 | for (int i=2;i<=num;i++) while (num % i == 0) { 20 | //此时i是num的一个质因数 21 | num /= i; 22 | if (i == curr.n) curr.s ++; 23 | else { 24 | if (curr.n != 0) l.push_back(curr); 25 | curr.n = i; 26 | curr.s = 1; 27 | } 28 | } 29 | if (curr.n != 0) l.push_back(curr); 30 | } 31 | inline void outputfjzys(int num){//这个函数仅供学习分解质因数过程使用,在程序中没有调用 32 | for (int i=2;i<=num;i++) { 33 | while(num % i == 0) { 34 | printf("%d ",i); 35 | num /= i; 36 | } 37 | } 38 | printf("\n"); 39 | } 40 | inline bool comp(const zys &a,const zys &b) { 41 | if (a.n < b.n) return true; 42 | if (a.n == b.n && a.s > b.s) return true; 43 | return false; 44 | } 45 | long long qpow(long long di,long long zhi,long long mod) { 46 | if (zhi == 0) return 1 % mod; 47 | if (zhi == 1) return di % mod; 48 | long long ret = qpow(di,zhi/2,mod) % mod; 49 | ret = (ret * ret) % mod; 50 | if (zhi % 2) ret = ret * (di % mod); 51 | return ret % mod; 52 | } 53 | int main() { 54 | int n,q;//q为取mod的值 55 | scanf("%d%d",&n,&q); 56 | int MAX = 0; 57 | for (int i=0;i 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | //两倍空间公式 { 8 | #define node (l+r) | (l!=r) 9 | #define mid (l+r)/2 10 | #define lson (l+mid) | (l != mid) 11 | #define rson (mid+1+r) | (mid+1 != r) 12 | //两倍空间公式 } 13 | struct segtree { 14 | long long sum; 15 | long long lazy; 16 | }tr[200005]; 17 | long long init[100005]; 18 | inline void push_up(int l,int r) { 19 | tr[node].sum = tr[lson].sum + tr[rson].sum; 20 | } 21 | void build_tree(int l,int r) { 22 | if (l == r) { 23 | tr[node].sum = init[l]; 24 | } 25 | else { 26 | build_tree(l,mid); 27 | build_tree(mid+1,r); 28 | push_up(l,r); 29 | } 30 | } 31 | long long sum(int l,int r,int L,int R) {//小写的l和r是当前节点区间,大写的L和R是要操作的区间 32 | if (l == L && r == R) return tr[node].sum; 33 | else { 34 | if (R <= mid) return (R - L + 1LL) * tr[node].lazy + sum(l,mid,L,R); 35 | if (L >= mid + 1) return (R - L + 1LL) * tr[node].lazy + sum(mid+1,r,L,R); 36 | return (R - L + 1LL) * tr[node].lazy + sum(l,mid,L,mid) + sum(mid+1,r,mid+1,R); 37 | } 38 | } 39 | void add(int l,int r,int L,int R,int d) { 40 | tr[node].sum += (R - L + 1) * d; 41 | if (l == L && r == R) { 42 | tr[node].lazy += d; 43 | } 44 | else { 45 | if (R <= mid) { 46 | add(l,mid,L,R,d); 47 | } 48 | else if (L >= mid + 1) { 49 | add(mid+1,r,L,R,d); 50 | } 51 | else { 52 | add(l,mid,L,mid,d); 53 | add(mid+1,r,mid+1,R,d); 54 | } 55 | } 56 | } 57 | int main() { 58 | int n,q; 59 | while (scanf("%d%d",&n,&q) == 2) { 60 | memset(tr,0,sizeof(tr)); 61 | for (int i=1;i<=n;i++) scanf("%lld",&init[i]); 62 | build_tree(1,n); 63 | while (q --) { 64 | int cmd; 65 | scanf("%d",&cmd); 66 | if (cmd == 2) { 67 | int a,b; 68 | scanf("%d%d",&a,&b); 69 | printf("%lld\n",sum(1,n,a,b)); 70 | } 71 | else { 72 | int a,b; 73 | long long c; 74 | scanf("%d%d%lld",&a,&b,&c); 75 | add(1,n,a,b,c); 76 | } 77 | } 78 | } 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /杂项/卡常大师.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize(2) 2 | #pragma GCC optimize(3) 3 | #pragma GCC optimize("Ofast") 4 | #pragma GCC optimize("inline") 5 | #pragma GCC optimize("-fgcse") 6 | #pragma GCC optimize("-fgcse-lm") 7 | #pragma GCC optimize("-fipa-sra") 8 | #pragma GCC optimize("-ftree-pre") 9 | #pragma GCC optimize("-ftree-vrp") 10 | #pragma GCC optimize("-fpeephole2") 11 | #pragma GCC optimize("-ffast-math") 12 | #pragma GCC optimize("-fsched-spec") 13 | #pragma GCC optimize("unroll-loops") 14 | #pragma GCC optimize("-falign-jumps") 15 | #pragma GCC optimize("-falign-loops") 16 | #pragma GCC optimize("-falign-labels") 17 | #pragma GCC optimize("-fdevirtualize") 18 | #pragma GCC optimize("-fcaller-saves") 19 | #pragma GCC optimize("-fcrossjumping") 20 | #pragma GCC optimize("-fthread-jumps") 21 | #pragma GCC optimize("-funroll-loops") 22 | #pragma GCC optimize("-fwhole-program") 23 | #pragma GCC optimize("-freorder-blocks") 24 | #pragma GCC optimize("-fschedule-insns") 25 | #pragma GCC optimize("inline-functions") 26 | #pragma GCC optimize("-ftree-tail-merge") 27 | #pragma GCC optimize("-fschedule-insns2") 28 | #pragma GCC optimize("-fstrict-aliasing") 29 | #pragma GCC optimize("-fstrict-overflow") 30 | #pragma GCC optimize("-falign-functions") 31 | #pragma GCC optimize("-fcse-skip-blocks") 32 | #pragma GCC optimize("-fcse-follow-jumps") 33 | #pragma GCC optimize("-fsched-interblock") 34 | #pragma GCC optimize("-fpartial-inlining") 35 | #pragma GCC optimize("no-stack-protector") 36 | #pragma GCC optimize("-freorder-functions") 37 | #pragma GCC optimize("-findirect-inlining") 38 | #pragma GCC optimize("-fhoist-adjacent-loads") 39 | #pragma GCC optimize("-frerun-cse-after-loop") 40 | #pragma GCC optimize("inline-small-functions") 41 | #pragma GCC optimize("-finline-small-functions") 42 | #pragma GCC optimize("-ftree-switch-conversion") 43 | #pragma GCC optimize("-foptimize-sibling-calls") 44 | #pragma GCC optimize("-fexpensive-optimizations") 45 | #pragma GCC optimize("-funsafe-loop-optimizations") 46 | #pragma GCC optimize("inline-functions-called-once") 47 | #pragma GCC optimize("-fdelete-null-pointer-checks") 48 | -------------------------------------------------------------------------------- /图论/网络流/最小费用最大流.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int INF = 0x3f3f3f3f; 4 | struct Edge{ 5 | int u; 6 | int v; 7 | int f; 8 | int c; 9 | int next; 10 | }e[100005]; 11 | int head[5005]; 12 | int pre[5005]; 13 | int n,m,s,t; 14 | int ecnt; 15 | inline void AddEdge(int _u,int _v,int _f,int _c) { 16 | e[ecnt].next = head[_u]; 17 | head[_u] = ecnt; 18 | e[ecnt].u = _u; 19 | e[ecnt].v = _v; 20 | e[ecnt].f = _f; 21 | e[ecnt].c = _c; 22 | ecnt++; 23 | } 24 | inline void Add(int _u,int _v,int _f,int _c) { 25 | AddEdge(_u,_v,_f,_c); 26 | AddEdge(_v,_u,0,-_c); 27 | } 28 | int dis[5005]; 29 | bool inq[5005]; 30 | bool SPFA(int s,int t) { 31 | queue q; 32 | q.push(s); 33 | memset(dis,0x3f,sizeof(dis)); 34 | memset(inq,0,sizeof(inq)); 35 | memset(pre,-1,sizeof(pre)); 36 | inq[s] = true; 37 | dis[s] = 0; 38 | while (!q.empty()) { 39 | int cur = q.front(); 40 | q.pop(); 41 | inq[cur] = false; 42 | for (int i = head[cur];i != -1;i = e[i].next) { 43 | if (e[i].f > 0 && dis[e[i].v] > dis[cur] + e[i].c) { 44 | dis[e[i].v] = dis[cur] + e[i].c; 45 | pre[e[i].v] = i; 46 | if (!inq[e[i].v]) { 47 | inq[e[i].v] = true; 48 | q.push(e[i].v); 49 | } 50 | } 51 | } 52 | } 53 | return dis[t] != INF; 54 | } 55 | void MICMAF(int s,int t,int &flow,int &cost) { 56 | flow = 0; 57 | cost = 0; 58 | while (SPFA(s,t)) { 59 | int minF = INF; 60 | for (int i=pre[t];i != -1;i=pre[e[i].u]) minF = min(minF,e[i].f); 61 | flow += minF; 62 | for (int i=pre[t];i != -1;i=pre[e[i].u]) { 63 | e[i].f -= minF; 64 | e[i^1].f += minF; 65 | } 66 | cost += dis[t] * minF; 67 | } 68 | } 69 | vector path[2]; 70 | void dfs(int u,int p) { 71 | for (int i=head[u];~i;i=e[i].next) { 72 | if ( (i & 1) == 0 && e[i].f == 0) { 73 | if (e[i].v == (u ^ 1) ) path[p].push_back(e[i].u/2); 74 | dfs(e[i].v,p); 75 | } 76 | } 77 | } 78 | int main() { 79 | scanf("%d%d%d%d",&n,&m,&s,&t); 80 | memset(head,-1,sizeof(head)); 81 | for (int i=0;i 3 | using namespace std; 4 | int bs; 5 | struct query { 6 | int l,r,x,id; 7 | friend bool operator < (const query &u,const query &v) { 8 | if (u.l/bs != v.l/bs) return u.l/bs < v.l/bs; 9 | if (u.r/bs != v.r/bs) return u.r/bs < v.r/bs; 10 | return u.x < v.x; 11 | } 12 | }Q[100000]; 13 | int qcnt; 14 | struct modify { 15 | int pos,last,val; 16 | }M[100000]; 17 | int mcnt; 18 | int a[200005]; 19 | int last[200005]; 20 | int ans[200005]; 21 | int cnt[200005]; 22 | int scnt[200005]; 23 | bool exist[200005]; 24 | void update(int x) { 25 | if (exist[x]) { 26 | scnt[cnt[a[x]]] --; 27 | cnt[a[x]] --; 28 | scnt[cnt[a[x]]] ++; 29 | } 30 | else { 31 | scnt[cnt[a[x]]] --; 32 | cnt[a[x]] ++; 33 | scnt[cnt[a[x]]] ++; 34 | } 35 | exist[x] ^= 1; 36 | } 37 | void change(int mi) { 38 | int x = M[mi].pos; 39 | if (exist[x]) { 40 | update(x); 41 | a[x] = M[mi].val; 42 | update(x); 43 | } 44 | else a[x] = M[mi].val; 45 | } 46 | void restore(int mi) { 47 | int x = M[mi].pos; 48 | if (exist[x]) { 49 | update(x); 50 | a[x] = M[mi].last; 51 | update(x); 52 | } 53 | else a[x] = M[mi].last; 54 | } 55 | unordered_map ls; 56 | int lscnt; 57 | int getls(int x) { 58 | if (ls.find(x) == ls.end()) ls[x] = ++lscnt; 59 | return ls[x]; 60 | } 61 | int main() { 62 | int n,q; 63 | scanf("%d%d",&n,&q); 64 | bs = pow(n,2.0/3.0); 65 | for (int i=1;i<=n;i++) { 66 | int x; 67 | scanf("%d",&x); 68 | a[i] = getls(x); 69 | last[i] = a[i]; 70 | } 71 | while (q --) { 72 | int t,l,r; 73 | scanf("%d%d%d",&t,&l,&r); 74 | if (t == 1) { 75 | Q[qcnt] = (query){l,r,mcnt-1,qcnt}; 76 | qcnt ++; 77 | } 78 | else { 79 | r = getls(r); 80 | M[mcnt++] = (modify){l,last[l],r}; 81 | last[l] = r; 82 | } 83 | } 84 | sort(Q,Q+qcnt); 85 | int l=1,r=0; 86 | int mi=-1; 87 | for (int i=0;i Q[i].x) restore(mi--); 90 | while (r < Q[i].r) update(++r); 91 | while (r > Q[i].r) update(r--); 92 | while (l < Q[i].l) update(l++); 93 | while (l > Q[i].l) update(--l); 94 | int cur = 1; 95 | while (scnt[cur] > 0) cur ++; 96 | ans[Q[i].id] = cur; 97 | } 98 | for (int i=0;i 4 | using namespace std; 5 | const int maxn = 505; 6 | const long long inf = 0x3f3f3f3f; 7 | struct Matrix { 8 | int n; 9 | long long a[505][505]; 10 | }; 11 | struct KM:Matrix { 12 | long long hl[maxn],hr[maxn],slk[maxn]; 13 | int fl[maxn],fr[maxn],pre[maxn]; 14 | bool vl[maxn],vr[maxn]; 15 | queue q; 16 | bool check(int i) { 17 | vl[i] = 1; 18 | if (fl[i] != -1) { 19 | q.push(fl[i]); 20 | vr[fl[i]] = true; 21 | return true; 22 | } 23 | while (i != -1) { 24 | fl[i] = pre[i]; 25 | swap(i,fr[fl[i]]); 26 | } 27 | return 0; 28 | } 29 | void bfs(int s) { 30 | memset(slk,0x3f,sizeof(slk)); 31 | memset(vl,0,sizeof(vl)); 32 | memset(vr,0,sizeof(vr)); 33 | while (!q.empty()) q.pop(); 34 | q.push(s); 35 | vr[s] = true; 36 | while (true) { 37 | long long d; 38 | while (!q.empty()) { 39 | for (int i=0,j=q.front();i= d) { 42 | pre[i] = j; 43 | if (d) slk[i] = d; 44 | else if (!check(i)) return; 45 | } 46 | } 47 | q.pop(); 48 | } 49 | d = inf; 50 | for (int i=0;i slk[i]) d = slk[i]; 52 | for (int i=0;i 3 | #include 4 | #include 5 | using namespace std; 6 | const int INF = 0x3f3f3f3f; 7 | int n; 8 | struct Pos { 9 | int x,y,id; 10 | friend bool operator < (const Pos &a,const Pos &b) { 11 | if (a.x == b.x) return a.y < b.y; 12 | return a.x < b.x; 13 | } 14 | }p[100000]; 15 | struct Edge { 16 | int u,v,w; 17 | friend bool operator < (const Edge &a,const Edge &b) { 18 | return a.w < b.w; 19 | } 20 | }e[400000]; 21 | int ecnt; 22 | struct DATA { 23 | int w; 24 | int id; 25 | }tr[100001]; 26 | inline int lowbit(int x) { 27 | return x & (-x); 28 | } 29 | void find_vertice(int u,int pos,int w) { 30 | DATA cur; 31 | cur.w = INF; 32 | for (int i=pos;i<=n;i+=lowbit(i)) if (tr[i].w < cur.w) cur = tr[i]; 33 | if (cur.w != INF) e[ecnt++] = (Edge){u,cur.id,cur.w-w}; 34 | } 35 | void insert_vertice(int u,int pos,int w) { 36 | for (int i=pos;i>=1;i-=lowbit(i)) if (w < tr[i].w) { 37 | tr[i].w = w; 38 | tr[i].id = u; 39 | } 40 | } 41 | int d[100000]; 42 | int lsd[100000]; 43 | void build_graph() { 44 | memset(tr,0x3f,sizeof(tr)); 45 | sort(p,p+n); 46 | //离散化 47 | for (int i=0;i=0;i--) { 51 | int pos = lsd[i]; 52 | int w = p[i].x + p[i].y; 53 | find_vertice(p[i].id,pos,w); 54 | insert_vertice(p[i].id,pos,w); 55 | } 56 | } 57 | int f[100000]; 58 | int find(int x) { 59 | if (f[x] != x) f[x] = find(f[x]); 60 | return f[x]; 61 | } 62 | void uni(int u,int v) { 63 | f[find(u)] = find(v); 64 | } 65 | long long kruskal() { 66 | sort(e,e+ecnt); 67 | int cnt = 0; 68 | long long sum = 0; 69 | for (int i=0;i 2 | #include 3 | using namespace std; 4 | long long n,m,p; 5 | long long a[100005]; 6 | struct node { 7 | long long sum; 8 | long long add,mul;//lazy-tag 9 | node *l,*r; 10 | node():sum(0),add(0),mul(1),l(NULL),r(NULL){}; 11 | }root; 12 | inline void PushUp(node *n) { 13 | n->sum = (n->l->sum + n->r-> sum) % p; 14 | } 15 | void build_tree(node *n,int lv,int rv) { 16 | if (lv == rv) n->sum = a[lv] % p;//其实可以在这读入,不必使用row数组 17 | else { 18 | int mid = (lv + rv) >> 1; 19 | n->l = new node; 20 | n->r = new node; 21 | build_tree(n->l,lv,mid); 22 | build_tree(n->r,mid+1,rv); 23 | PushUp(n); 24 | } 25 | } 26 | inline void PushDown(node *n,int len) { 27 | n->l->add = ((n->l->add * n->mul)%p + n->add)%p; 28 | n->r->add = ((n->r->add * n->mul)%p + n->add)%p; 29 | n->l->mul = (n->l->mul * n->mul)%p; 30 | n->r->mul = (n->r->mul * n->mul)%p; 31 | n->l->sum = (n->l->sum * n->mul)%p + (n->add * (len - (len>>1)))%p; 32 | //很多人以为len的计算写错了,举个例子,当前节点为1...3,len=3,3/2=1,左节点长度为2,右节点长度为1,所以左节点长度为len-len/2 33 | n->r->sum = (n->r->sum * n->mul)%p + (n->add * (len>>1))%p; 34 | n->add = 0; 35 | n->mul = 1; 36 | } 37 | void update(node *n,int l,int r,int lv,int rv,long long k,int o) { 38 | if (l == lv && r == rv) { 39 | if (o == 1) { 40 | n->add = (n->add * k)%p; 41 | n->mul = (n->mul * k)%p; 42 | n->sum = (n->sum * k)%p; 43 | } 44 | else { 45 | n->add = (n->add + k)%p; 46 | n->sum = (n->sum + k*(r-l+1))%p; 47 | } 48 | } 49 | else { 50 | PushDown(n,rv-lv+1);//先把这个节点的懒人标记做到两个子节点上 51 | int mid = (lv + rv) >> 1; 52 | if (r<=mid) update(n->l,l,r,lv,mid,k,o); 53 | else if (l > mid) update(n->r,l,r,mid+1,rv,k,o); 54 | else { 55 | update(n->l,l,mid,lv,mid,k,o); 56 | update(n->r,mid+1,r,mid+1,rv,k,o); 57 | } 58 | PushUp(n); 59 | } 60 | } 61 | long long query(node *n,int l,int r,int lv,int rv) { 62 | if (l == lv && r == rv) return n->sum %p; 63 | else { 64 | PushDown(n,rv-lv+1); 65 | int mid = (lv + rv) >> 1; 66 | if (r <= mid) return query(n->l,l,r,lv,mid); 67 | if (l > mid) return query(n->r,l,r,mid+1,rv); 68 | return (query(n->l,l,mid,lv,mid) + query(n->r,mid+1,r,mid+1,rv))%p; 69 | } 70 | } 71 | int main() { 72 | scanf("%lld%lld%lld",&n,&m,&p); 73 | for (int i=1;i<=n;i++) scanf("%lld",&a[i]); 74 | build_tree(&root,1,n); 75 | while(m--) { 76 | int o,x,y; 77 | scanf("%d%d%d",&o,&x,&y); 78 | if (o == 3) { 79 | printf("%lld\n",query(&root,x,y,1,n)); 80 | } 81 | else { 82 | long long k; 83 | scanf("%lld",&k); 84 | k = k %p; 85 | update(&root,x,y,1,n,k,o); 86 | } 87 | } 88 | return 0; 89 | } -------------------------------------------------------------------------------- /图论/缩点(Tarjan强连通分量).cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大,你只需要求出这个权值和。 3 | 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。 4 | */ 5 | #include 6 | using namespace std; 7 | const int maxn = 1e5+15; 8 | const int maxm = 1e6+15; 9 | int w[maxn]; 10 | int head[maxn]; 11 | struct Edge{ 12 | int u,v; 13 | int next; 14 | }e[maxm]; 15 | int ecnt = 0; 16 | inline void AddEdge(int u,int v) { 17 | e[ecnt].u = u; 18 | e[ecnt].v = v; 19 | e[ecnt].next = head[u]; 20 | head[u] = ecnt; 21 | ecnt ++; 22 | } 23 | int rt[maxn];//root 24 | int nw[maxn];//缩点后的新权值 25 | int dfn[maxn]; 26 | int low[maxn]; 27 | int tjtime;//tarjan time 28 | stack s; 29 | bool ins[maxn]; 30 | int subg = 0;//子图数量 31 | void tarjan(int u) { 32 | dfn[u] = ++tjtime; 33 | low[u] = tjtime; 34 | s.push(u); 35 | ins[u] = true; 36 | for (int i=head[u];i != -1;i=e[i].next) { 37 | int v = e[i].v; 38 | if (!dfn[v]) { 39 | tarjan(v); 40 | low[u] = min(low[u],low[v]); 41 | } 42 | else if (ins[v]) low[u] = min(low[u],dfn[v]); 43 | } 44 | if (low[u] == dfn[u]) {//一个强连通分量 45 | subg ++; 46 | while (!s.empty()) { 47 | int cur = s.top(); 48 | s.pop(); 49 | ins[cur] = false; 50 | rt[cur] = subg; 51 | nw[subg] += w[cur]; 52 | if (cur == u) break; 53 | } 54 | } 55 | } 56 | int dis[maxn]; 57 | bool inq[maxn]; 58 | queue q; 59 | int spfa(int u) { 60 | memset(dis,0,sizeof(dis)); 61 | memset(inq,0,sizeof(inq)); 62 | q.push(u); 63 | inq[u] = true; 64 | dis[u] = nw[u]; 65 | int maxdis = nw[u]; 66 | while (!q.empty()) { 67 | int cur = q.front(); 68 | q.pop(); 69 | inq[cur] = false; 70 | for (int i=head[cur];i != -1;i=e[i].next) { 71 | int v = e[i].v; 72 | if (dis[v] < dis[cur] + nw[v]) { 73 | dis[v] = dis[cur] + nw[v]; 74 | maxdis = max(maxdis,dis[v]); 75 | if (!inq[v]) { 76 | q.push(v); 77 | inq[v] = true; 78 | } 79 | } 80 | } 81 | } 82 | return maxdis; 83 | } 84 | int mx[maxm],my[maxm]; 85 | int main() { 86 | int n,m; 87 | scanf("%d%d",&n,&m); 88 | memset(head,-1,sizeof(head)); 89 | for (int i=1;i<=n;i++) scanf("%d",&w[i]); 90 | for (int i=1;i<=m;i++) { 91 | scanf("%d%d",&mx[i],&my[i]); 92 | AddEdge(mx[i],my[i]); 93 | } 94 | for (int i=1;i<=n;i++) if (!rt[i]) tarjan(i); 95 | memset(head,-1,sizeof(head)); 96 | ecnt = 0; 97 | for (int i=1;i<=m;i++) { 98 | int x = rt[mx[i]]; 99 | int y = rt[my[i]]; 100 | if (x != y) AddEdge(x,y); 101 | } 102 | int ans = 0; 103 | for (int i=1;i<=subg;i++) ans = max(ans,spfa(i)); 104 | printf("%d\n",ans); 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /数学/Pollard_Rho.cpp: -------------------------------------------------------------------------------- 1 | //POJ 2429 给出两个数的gcd和lcm,求这两个数,多解时输出和最小的解 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | long long gcd(long long a,long long b) { 7 | if (b == 0) return a; 8 | return gcd(b,a%b); 9 | } 10 | long long mul(long long a,long long b,long long mod){ 11 | long long ret=0; 12 | while(b) { 13 | if(b & 1) { 14 | ret += a; 15 | ret %= mod; 16 | } 17 | a <<= 1; 18 | a %= mod; 19 | b >>= 1; 20 | } 21 | return ret; 22 | } 23 | long long pow(long long a,long long b,long long mod) { 24 | long long ret = 1; 25 | while(b) { 26 | if(b & 1) ret = mul(ret,a,mod); 27 | a = mul(a,a,mod); 28 | b >>= 1; 29 | } 30 | return ret; 31 | } 32 | bool check(long long a,long long n){ 33 | long long x = n - 1; 34 | int t = 0; 35 | while((x & 1) == 0) { 36 | x >>= 1; 37 | t ++; 38 | } 39 | x = pow(a,x,n); 40 | long long y; 41 | for(int i=1;i<=t;i++) { 42 | y = mul(x,x,n); 43 | if(y == 1 && x != 1 && x != n - 1) return true; 44 | x = y; 45 | } 46 | if(y != 1) return true; 47 | return false; 48 | } 49 | bool Miller_Rabin(long long n) { 50 | if(n == 2) return true; 51 | if(n == 1 || !(n & 1)) return false; 52 | const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37}; 53 | for(int i = 0; i < 12; i++) { 54 | if (arr[i] >= n) break; 55 | if(check(arr[i], n)) return false; 56 | } 57 | return true; 58 | } 59 | long long Pollard_rho(long long n,int c) { 60 | long long i=1,k=2,x,y,d; 61 | y = x = rand() % n; 62 | while (true) { 63 | i ++; 64 | x = (mul(x,x,n) + c) % n; 65 | d = gcd(y-x,n); 66 | if (d > 1 && d < n) return d; 67 | if (y == x) break; 68 | if (i == k) { 69 | y = x; 70 | k <<= 1; 71 | } 72 | } 73 | return true; 74 | } 75 | void factorize(long long n,map &cnt,int c = 107) { 76 | if (n == 1) return; 77 | if (Miller_Rabin(n)) { 78 | cnt[n] ++; 79 | return; 80 | } 81 | long long p = n; 82 | while (p >= n) p = Pollard_rho(p,c--); 83 | factorize(p,cnt,c); 84 | factorize(n/p,cnt,c); 85 | } 86 | long long g,l,n,a,b; 87 | map cnt; 88 | void dfs(map::iterator it,long long val) { 89 | if (it == cnt.end()) { 90 | long long cur_a = val * g; 91 | long long cur_b = (n / val) * g; 92 | //printf("(debug)%lld %lld\n",cur_a,cur_b); 93 | if (cur_a + cur_b < a + b && gcd(cur_a,cur_b) == g) { 94 | a = min(cur_a,cur_b); 95 | b = max(cur_a,cur_b); 96 | } 97 | } 98 | else { 99 | map::iterator nit = it; 100 | nit ++; 101 | for (int i=0;i<=it->second;i++) { 102 | dfs(nit,val); 103 | val *= it->first; 104 | } 105 | } 106 | } 107 | int main() { 108 | while (scanf("%lld%lld",&g,&l) == 2) { 109 | n = l / g; 110 | cnt.clear(); 111 | factorize(n,cnt); 112 | /* 113 | printf("-----DEBUG BEGIN-----\n"); 114 | for (auto x:cnt) printf("%lld %d\n",x.first,x.second); 115 | printf("-----DEBUG END -----\n"); 116 | */ 117 | a = b = 0x3f3f3f3f3f3f3f3f; 118 | dfs(cnt.begin(),1); 119 | printf("%lld %lld\n",a,b); 120 | } 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /杂项/BM递推.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | #define rep(i, a, n) for (long long i = a; i < n; i++) 5 | #define per(i, a, n) for (long long i = n - 1; i >= a; i--) 6 | #define pb push_back 7 | #define mp make_pair 8 | #define all(x) (x).begin(), (x).end() 9 | #define fi first 10 | #define se second 11 | #define SZ(x) ((long long)(x).size()) 12 | typedef vector VI; 13 | typedef long long ll; 14 | typedef pair PII; 15 | const ll mod = 1e9 + 7; 16 | ll powmod(ll a, ll b) { 17 | ll res = 1; a %= mod; assert(b >= 0); for (; b; b >>= 1) { 18 | if (b & 1)res = res * a%mod; a = a * a%mod; 19 | }return res; 20 | } 21 | // head 22 | long long n; 23 | namespace linear_seq 24 | { 25 | const long long N = 10010; 26 | ll res[N], base[N], _c[N], _md[N]; 27 | 28 | vector Md; 29 | void mul(ll *a, ll *b, long long k) 30 | { 31 | rep(i, 0, k + k) _c[i] = 0; 32 | rep(i, 0, k) if (a[i]) rep(j, 0, k) 33 | _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod; 34 | for (long long i = k + k - 1; i >= k; i--) if (_c[i]) 35 | rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - 36 | _c[i] * _md[Md[j]]) % mod; 37 | rep(i, 0, k) a[i] = _c[i]; 38 | } 39 | long long solve(ll n, VI a, VI b) 40 | { // a 系数 b 初值 b[n+1]=a[0]*b[n]+... 41 | // printf("%d\n",SZ(b)); 42 | ll ans = 0, pnt = 0; 43 | long long k = SZ(a); 44 | assert(SZ(a) == SZ(b)); 45 | rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1; 46 | Md.clear(); 47 | rep(i, 0, k) if (_md[i] != 0) Md.push_back(i); 48 | rep(i, 0, k) res[i] = base[i] = 0; 49 | res[0] = 1; 50 | while ((1ll << pnt) <= n) pnt++; 51 | for (long long p = pnt; p >= 0; p--) 52 | { 53 | mul(res, res, k); 54 | if ((n >> p) & 1) 55 | { 56 | for (long long i = k - 1; i >= 0; i--) res[i + 1] = res[i]; res[0] = 0; 57 | rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - 58 | res[k] * _md[Md[j]]) % mod; 59 | } 60 | } 61 | rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod; 62 | if (ans < 0) ans += mod; 63 | return ans; 64 | } 65 | VI BM(VI s) 66 | { 67 | VI C(1, 1), B(1, 1); 68 | long long L = 0, m = 1, b = 1; 69 | rep(n, 0, SZ(s)) 70 | { 71 | ll d = 0; 72 | rep(i, 0, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod; 73 | if (d == 0) ++m; 74 | else if (2 * L <= n) 75 | { 76 | VI T = C; 77 | ll c = mod - d * powmod(b, mod - 2) % mod; 78 | while (SZ(C) < SZ(B) + m) C.pb(0); 79 | rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod; 80 | L = n + 1 - L; B = T; b = d; m = 1; 81 | } 82 | else 83 | { 84 | ll c = mod - d * powmod(b, mod - 2) % mod; 85 | while (SZ(C) < SZ(B) + m) C.pb(0); 86 | rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod; 87 | ++m; 88 | } 89 | } 90 | return C; 91 | } 92 | long long gao(VI a, ll n) 93 | { 94 | VI c = BM(a); 95 | c.erase(c.begin()); 96 | rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod; 97 | return solve(n, c, VI(a.begin(), a.begin() + SZ(c))); 98 | } 99 | }; 100 | 101 | int main() 102 | { 103 | for (int i=1;i<=30;i++) printf("%lld\n",linear_seq::gao(VI{1,1,2,3,5,8}, i)); 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /数据结构/主席树(区间k大值).cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 题目源自POJ 2104 3 | http://poj.org/problem?id=2104 4 | 由于指针TLE,非指针版本在此https://github.com/cyyself/OILife/blob/master/POJ/2104%20-%20K-th%20Number.cpp 5 | 6 | 参考资料: 7 | https://www.bilibili.com/video/av4619406 8 | https://blog.csdn.net/creatorx/article/details/75446472 9 | 10 | 我自己在网上看了许多主席树的代码,但都觉得不是很通俗易懂,后来看了一篇文章和一个视频才算有所了解。 11 | 自己写了一个用指针的版本,并且代码中有大量注释,希望能对大家有帮助。 12 | */ 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | struct DATA { 18 | int v; 19 | int pos; 20 | friend bool operator < (const DATA &a,const DATA &b) { 21 | return a.v < b.v; 22 | } 23 | }d[100005]; 24 | int rk[100005];//输入数据各个数字的值对应的rank,做离散化(为了方便就不用unique+cnt的方法了) 25 | struct node { 26 | node *l; 27 | node *r; 28 | int sum;//树上存储每个节点的sum 29 | }; 30 | node *root[100005]; 31 | void push_up(node *n) { 32 | n->sum = n->l->sum + n->r->sum; 33 | } 34 | node* create_and_copy_node(node *src) {//复制这个节点的信息,返回一个新创建的指针 35 | node *ret = new node; 36 | ret->l = src->l; 37 | ret->r = src->r; 38 | ret->sum = src->sum; 39 | return ret; 40 | } 41 | void insert(node *n,int l,int r,int pos) {//由于是单点增加,所以只需要传入pos参数就行了 42 | if (l == r) { 43 | n->sum ++; 44 | } 45 | else { 46 | int mid = (l + r) >> 1; 47 | if (pos <= mid) { 48 | //要修改的节点在左子树 49 | n->l = create_and_copy_node(n->l);//每当我们需要修改时,创建一个新的节点,并复制之前的信息 50 | insert(n->l,l,mid,pos); 51 | } 52 | else { 53 | n->r = create_and_copy_node(n->r); 54 | insert(n->r,mid+1,r,pos); 55 | } 56 | //因为是单点修改,不存在那种判断修改的区间是两个的情况了(实际上这种情况主席树也可以做) 57 | push_up(n); 58 | } 59 | } 60 | int query(node *x,node *y,int l,int r,int k) {//找到前缀和之差等于k的位置 61 | int cur = y->l->sum - x->l->sum; 62 | if (l == r) return l; 63 | else { 64 | int mid = (l + r) >> 1; 65 | if (k <= cur) { 66 | //答案在左子树 67 | return query(x->l,y->l,l,mid,k); 68 | } 69 | else { 70 | //答案在右子树 71 | return query(x->r,y->r,mid+1,r,k-cur); 72 | } 73 | } 74 | } 75 | /* 76 | 首先我们先对输入的数据进行离散化,将数字的值对应到它本身的排名。 77 | 我们构造一棵线段树,存储离散后的n个元素出现的次数。 78 | 例如有个排名为i的元素出现一次,我们就在线段树的i位置+1 79 | 但是一共会插入n个元素,如果每次构造一棵线段树显然MLE。 80 | 这时候我们就使用主席树,先复制原来的那棵线段树的节点指针。 81 | 因为线段树单点修改每次修改只会修改一条链(只需要新创建log n数量级的节点), 82 | 所以我们对于没有修改的部分可以继续用之前的指针, 83 | 来减少内存占用,这便是主席树。 84 | */ 85 | int read() { 86 | int ret = 0; 87 | int f = 1; 88 | char c = getchar(); 89 | while (!(c >= '0' && c <= '9')) { 90 | if (c == '-') f = -1; 91 | c = getchar(); 92 | } 93 | while (c >= '0' && c <= '9') { 94 | ret *= 10; 95 | ret += c - '0'; 96 | c = getchar(); 97 | } 98 | return ret * f; 99 | } 100 | int main() { 101 | int n,m; 102 | n = read(); 103 | m = read(); 104 | for (int i=1;i<=n;i++) { 105 | d[i].v = read(); 106 | d[i].pos = i; 107 | } 108 | sort(d+1,d+1+n); 109 | for (int i=1;i<=n;i++) rk[d[i].pos] = i;//把原始数据中输入的位置对应到rank 110 | 111 | //构造一个sum为0的root[0],因为主席树查询时可能出现之前时间的另一棵树不存在的情况 112 | root[0] = new node; 113 | root[0]->l = root[0]; 114 | root[0]->r = root[0]; 115 | root[0]->sum = 0; 116 | 117 | for (int i=1;i<=n;i++) { 118 | //先复制一遍之前的节点 119 | root[i] = create_and_copy_node(root[i-1]); 120 | insert(root[i],1,n,rk[i]); 121 | } 122 | 123 | while (m--) { 124 | int x,y,k; 125 | x = read(); 126 | y = read(); 127 | k = read(); 128 | int pos = query(root[x-1],root[y],1,n,k); 129 | printf("%d\n",d[pos].v); 130 | } 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /数据结构/普通有旋Treap.cpp: -------------------------------------------------------------------------------- 1 | //https://www.luogu.com.cn/problem/P3369 2 | #include 3 | using namespace std; 4 | const int maxn = 1e5+5; 5 | const int inf = 0x3f3f3f3f; 6 | struct Treap {//有旋Treap 7 | int sz[maxn];//子树大小 8 | int rd[maxn];//随机权值 9 | int cnt[maxn];//这个节点值的数量 10 | int val[maxn];//节点的数值 11 | int son[maxn][2]; 12 | int rt,nodecnt; 13 | void init() { 14 | for (int i=1;i val[node]); 45 | insert(son[node][d],x); 46 | if (rd[node] < rd[son[node][d]]) rotate(node,d^1); 47 | pushup(node); 48 | } 49 | } 50 | void del(int x) {del(rt,x);} 51 | void del(int &node,int x) { 52 | if (!node) return; 53 | if (x < val[node]) { 54 | del(son[node][0],x); 55 | } 56 | else if (x > val[node]) { 57 | del(son[node][1],x); 58 | } 59 | else { 60 | if (!son[node][0] && !son[node][1]) { 61 | cnt[node] --; 62 | sz[node] --; 63 | if (cnt[node] == 0) node = 0; 64 | } 65 | else if (son[node][0] && son[node][1]) { 66 | int d = (rd[son[node][0]] > rd[son[node][1]]); 67 | rotate(node,d); 68 | del(son[node][d],x); 69 | } 70 | else if (son[node][0]) { 71 | rotate(node,1); 72 | del(son[node][1],x); 73 | } 74 | else { 75 | rotate(node,0); 76 | del(son[node][0],x); 77 | } 78 | } 79 | pushup(node); 80 | } 81 | int getrankbyval(int x) {return getrankbyval(rt,x);} 82 | int getrankbyval(int node,int x) { 83 | if (!node) return 0; 84 | if (val[node] == x) return sz[son[node][0]] + 1; 85 | else if (val[node] < x) return sz[son[node][0]] + cnt[node] + getrankbyval(son[node][1],x); 86 | else return getrankbyval(son[node][0],x); 87 | } 88 | int getvalbyrank(int x) {return getvalbyrank(rt,x);} 89 | int getvalbyrank(int node,int x) { 90 | if (!node) return 0; 91 | if (sz[son[node][0]] >= x) return getvalbyrank(son[node][0],x); 92 | else if (sz[son[node][0]] + cnt[node] < x) 93 | return getvalbyrank(son[node][1],x-sz[son[node][0]]-cnt[node]); 94 | else return val[node]; 95 | } 96 | int pre(int x) {return pre(rt,x);} 97 | int pre(int node,int x) { 98 | if (!node) return -inf; 99 | if (val[node] >= x) return pre(son[node][0],x); 100 | else return max(val[node],pre(son[node][1],x)); 101 | } 102 | int nxt(int x) {return nxt(rt,x);} 103 | int nxt(int node,int x) { 104 | if (!node) return inf; 105 | if (val[node] <= x) return nxt(son[node][1],x); 106 | else return min(val[node],nxt(son[node][0],x)); 107 | } 108 | } tr; 109 | int main() { 110 | tr.init(); 111 | int q; 112 | scanf("%d",&q); 113 | while (q --) { 114 | int op,x; 115 | scanf("%d%d",&op,&x); 116 | switch (op) { 117 | case 1: 118 | tr.insert(x); 119 | break; 120 | case 2: 121 | tr.del(x); 122 | break; 123 | case 3: 124 | printf("%d\n",tr.getrankbyval(x)); 125 | break; 126 | case 4: 127 | printf("%d\n",tr.getvalbyrank(x)); 128 | break; 129 | case 5: 130 | printf("%d\n",tr.pre(x)); 131 | break; 132 | case 6: 133 | printf("%d\n",tr.nxt(x)); 134 | break; 135 | } 136 | } 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /数据结构/无旋Treap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int maxn = 1e5+5; 4 | struct Treap {//无旋Treap,注:按照权值和按照大小不能同时使用 5 | int sz[maxn]; 6 | int rd[maxn]; 7 | int val[maxn]; 8 | int son[maxn][2]; 9 | bool rev[maxn]; 10 | int rt,nodecnt; 11 | void init() { 12 | for (int i=1;i &buf) { 125 | if (!node) return; 126 | push_down(node); 127 | out(son[node][0],buf); 128 | buf.push_back(val[node]); 129 | out(son[node][1],buf); 130 | } 131 | void out(vector &buf) { 132 | out(rt,buf); 133 | } 134 | void reverse(int l,int r) { 135 | int t1,t2,t3; 136 | split_sz(rt,l-1,t1,t2); 137 | split_sz(t2,r-l+1,t2,t3); 138 | rev[t2] ^= 1; 139 | rt = merge(t1,merge(t2,t3)); 140 | } 141 | }tr; 142 | int main() { 143 | tr.init(); 144 | int n,m; 145 | scanf("%d%d",&n,&m); 146 | for (int i=1;i<=n;i++) tr.insert(i); 147 | while (m --) { 148 | int l,r; 149 | scanf("%d%d",&l,&r); 150 | tr.reverse(l,r); 151 | } 152 | vector ans; 153 | tr.out(ans); 154 | for (int i=0;i 3 | using namespace std; 4 | const int maxn = 1000005; 5 | const long long inf = 0x3f3f3f3f3f3f3f3f; 6 | vector g[maxn]; 7 | long long c[maxn]; 8 | int dep[maxn]; 9 | int dfn[maxn]; 10 | int ts; 11 | int up[maxn][20]; 12 | void dfs(int u,int f) { 13 | dfn[u] = ts ++; 14 | for (int i=1;(1< dep[y]) swap(x,y); 28 | int diff = dep[y] - dep[x]; 29 | for (int i=0;diff;i++) if (diff & (1 << i)) { 30 | y = up[y][i]; 31 | diff -= (1 << i); 32 | } 33 | for (int i=19;i>=0;i--) { 34 | if (up[x][i] != up[y][i]) { 35 | x = up[x][i]; 36 | y = up[y][i]; 37 | } 38 | } 39 | if (x == y) return x; 40 | else return up[x][0]; 41 | } 42 | bool ins[maxn]; 43 | stack used_s; 44 | bool used[maxn]; 45 | vector g2[maxn]; 46 | void clear_g2() { 47 | while (!used_s.empty()) { 48 | int u = used_s.top(); 49 | used_s.pop(); 50 | used[u] = false; 51 | g2[u].clear(); 52 | } 53 | } 54 | void add(int u,int v) { 55 | if (!used[u]) { 56 | used[u] = true; 57 | used_s.push(u); 58 | } 59 | g2[u].push_back(v); 60 | } 61 | bool key_node[maxn]; 62 | long long sum,MIN,MAX; 63 | long long down_cur[maxn],down_sz[maxn],down_MMIN[maxn],down_MMAX[maxn]; 64 | void dfs2(int u,int fa,long long up_cur,long long up_sz,long long up_MMIN,long long up_MMAX) { 65 | down_cur[u] = 0; 66 | down_sz[u] = key_node[u]; 67 | down_MMIN[u] = key_node[u]?0:inf; 68 | down_MMAX[u] = key_node[u]?0:-inf; 69 | if (key_node[u]) { 70 | sum += up_cur; 71 | MIN = min(MIN,up_MMIN); 72 | MAX = max(MAX,up_MMAX); 73 | up_MMIN = min(up_MMIN,0ll); 74 | up_MMAX = max(up_MMAX,0ll); 75 | up_sz += 1; 76 | } 77 | for (int i=0;i h; 110 | for (int i=0;i s; 118 | s.push(1); 119 | ins[1] = true; 120 | clear_g2(); 121 | for (int i=0;i 2 | using namespace std; 3 | namespace Geometry { 4 | const double eps = 1e-8; 5 | bool eq(double x,double y) { 6 | return abs(x-y) < eps; 7 | } 8 | int sgn(double x) { 9 | if (eq(x,0)) return 0; 10 | else return x>0?1:-1; 11 | } 12 | struct Point { 13 | double x,y; 14 | Point() { 15 | x = 0; 16 | y = 0; 17 | } 18 | Point(double _x,double _y) { 19 | x = _x; 20 | y = _y; 21 | } 22 | Point spin(double ddeg) { 23 | double deg = atan2(y,x); 24 | double r = sqrt(x * x + y * y); 25 | return Point(r * cos(deg+ddeg),r * sin(deg+ddeg)); 26 | } 27 | friend Point operator + (const Point &a,const Point &b) { 28 | return Point(a.x+b.x,a.y+b.y); 29 | } 30 | friend Point operator - (const Point &a,const Point &b) { 31 | return Point(a.x-b.x,a.y-b.y); 32 | } 33 | friend double operator * (const Point &a,const Point &b) { 34 | return a.x * b.x + a.y * b.y; 35 | } 36 | friend double operator ^ (const Point &a,const Point &b) { 37 | return a.x * b.y - a.y * b.x;//cross product 38 | } 39 | friend Point operator * (double k,Point p) { 40 | return Point(p.x*k,p.y*k); 41 | } 42 | }; 43 | struct Line { 44 | Point u,v; 45 | Point d; 46 | double deg; 47 | Line() { 48 | deg = 0; 49 | } 50 | Line(const Point &_u,const Point &_v) { 51 | u = _u; 52 | v = _v; 53 | d = v - u; 54 | deg = atan2(d.y,d.x); 55 | } 56 | friend bool operator < (const Line &a,const Line &b) { 57 | if (eq(a.deg,b.deg)) return sgn((a.v-a.u) ^ (b.v-a.u)) > 0; 58 | //第二个确实是a.u不是b.u,这里没打错 59 | return a.deg < b.deg; 60 | } 61 | }; 62 | template 63 | class mydeque : public deque { 64 | public: 65 | T front_sec() { 66 | T tmp = this->front(); 67 | this->pop_front(); 68 | T res = this->front(); 69 | this->push_front(tmp); 70 | return res; 71 | } 72 | T back_sec() { 73 | T tmp = this->back(); 74 | this->pop_back(); 75 | T res = this->back(); 76 | this->push_back(tmp); 77 | return res; 78 | } 79 | }; 80 | Point proj(Point a,Point b,Point p) {//点p在直线ab的投影 81 | Point d = b - a; 82 | Point r = p - a; 83 | return a + d * ((r * d)/(d * d)); 84 | } 85 | double dis(Point a,Point b) { 86 | double dx = b.x - a.x; 87 | double dy = b.y - a.y; 88 | return sqrt(dx * dx + dy * dy); 89 | } 90 | Point inter(Line a,Line b) { 91 | Point c = b.u - a.u; 92 | return b.u + ((c^a.d) / (a.d^b.d)) * b.d; 93 | } 94 | bool check(Point p,Line l) { 95 | return sgn(l.d ^ (p-l.u)) > 0;//点在直线左侧 96 | } 97 | void HPI(vector lines,vector &result) { 98 | result.clear(); 99 | sort(lines.begin(),lines.end()); 100 | vector lines; 101 | auto last_line = lines_in[0]; 102 | for (auto x:lines_in) { 103 | if (!eq(x.deg,last_line.deg)) lines.push_back(last_line); 104 | last_line = x; 105 | } 106 | lines.push_back(last_line); 107 | if (lines.size() < 3) return; 108 | mydeque q; 109 | for (int i=0;i= 2 && !check(inter(q.back_sec(),q.back()),lines[i])) q.pop_back(); 111 | while (q.size() >= 2 && !check(inter(q.front_sec(),q.front()),lines[i])) q.pop_front(); 112 | q.push_back(lines[i]); 113 | } 114 | while (q.size() >= 2 && !check(inter(q.back_sec(),q.back()),q.front())) q.pop_back(); 115 | while (q.size() >= 2 && !check(inter(q.front_sec(),q.front()),q.back())) q.pop_front(); 116 | Line fi = q.front(); 117 | q.pop_front(); 118 | Line last = fi; 119 | while (!q.empty()) { 120 | auto cur = q.front(); 121 | q.pop_front(); 122 | result.push_back(inter(last,cur)); 123 | if (q.empty()) { 124 | result.push_back(inter(cur,fi)); 125 | } 126 | last = cur; 127 | } 128 | } 129 | double poly_area(const vector &p) {//p需按照极角排序 130 | if (p.size() < 3) return 0; 131 | //Point fi = *p.begin(); 132 | double sum = 0; 133 | for (int i=0;i lines; 146 | while (n --) { 147 | int m; 148 | scanf("%d",&m); 149 | vector tmp; 150 | for (int i=0;i result; 160 | HPI(lines,result); 161 | printf("%0.3f\n",poly_area(result)); 162 | } 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /杂项/fastIO.cpp: -------------------------------------------------------------------------------- 1 | namespace fastIO 2 | { 3 | #define BUF_SIZE 100000 4 | #define OUT_SIZE 100000 5 | #define ll long long 6 | //fread->read 7 | bool IOerror=0; 8 | inline char nc(){ 9 | static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; 10 | if (p1==pend){ 11 | p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); 12 | if (pend==p1){IOerror=1;return -1;} 13 | //{printf("IO error!\n");system("pause");for (;;);exit(0);} 14 | } 15 | return *p1++; 16 | } 17 | inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} 18 | inline void read(int &x){ 19 | bool sign=0; char ch=nc(); x=0; 20 | for (;blank(ch);ch=nc()); 21 | if (IOerror)return; 22 | if (ch=='-')sign=1,ch=nc(); 23 | for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 24 | if (sign)x=-x; 25 | } 26 | inline void read(ll &x){ 27 | bool sign=0; char ch=nc(); x=0; 28 | for (;blank(ch);ch=nc()); 29 | if (IOerror)return; 30 | if (ch=='-')sign=1,ch=nc(); 31 | for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 32 | if (sign)x=-x; 33 | } 34 | inline void read(double &x){ 35 | bool sign=0; char ch=nc(); x=0; 36 | for (;blank(ch);ch=nc()); 37 | if (IOerror)return; 38 | if (ch=='-')sign=1,ch=nc(); 39 | for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 40 | if (ch=='.'){ 41 | double tmp=1; ch=nc(); 42 | for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); 43 | } 44 | if (sign)x=-x; 45 | } 46 | inline void read(char *s){ 47 | char ch=nc(); 48 | for (;blank(ch);ch=nc()); 49 | if (IOerror)return; 50 | for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; 51 | *s=0; 52 | } 53 | inline void read(char &c){ 54 | for (c=nc();blank(c);c=nc()); 55 | if (IOerror){c=-1;return;} 56 | } 57 | //getchar->read 58 | inline void read1(int &x){ 59 | char ch;int bo=0;x=0; 60 | for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1; 61 | for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar()); 62 | if (bo)x=-x; 63 | } 64 | inline void read1(ll &x){ 65 | char ch;int bo=0;x=0; 66 | for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1; 67 | for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar()); 68 | if (bo)x=-x; 69 | } 70 | inline void read1(double &x){ 71 | char ch;int bo=0;x=0; 72 | for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1; 73 | for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar()); 74 | if (ch=='.'){ 75 | double tmp=1; 76 | for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar()); 77 | } 78 | if (bo)x=-x; 79 | } 80 | inline void read1(char *s){ 81 | char ch=getchar(); 82 | for (;blank(ch);ch=getchar()); 83 | for (;!blank(ch);ch=getchar())*s++=ch; 84 | *s=0; 85 | } 86 | inline void read1(char &c){for (c=getchar();blank(c);c=getchar());} 87 | //scanf->read 88 | inline void read2(int &x){scanf("%d",&x);} 89 | inline void read2(ll &x){ 90 | #ifdef _WIN32 91 | scanf("%I64d",&x); 92 | #else 93 | #ifdef __linux 94 | scanf("%lld",&x); 95 | #else 96 | puts("error:can't recognize the system!"); 97 | #endif 98 | #endif 99 | } 100 | inline void read2(double &x){scanf("%lf",&x);} 101 | inline void read2(char *s){scanf("%s",s);} 102 | inline void read2(char &c){scanf(" %c",&c);} 103 | inline void readln2(char *s){gets(s);} 104 | //fwrite->write 105 | struct Ostream_fwrite{ 106 | char *buf,*p1,*pend; 107 | Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;} 108 | void out(char ch){ 109 | if (p1==pend){ 110 | fwrite(buf,1,BUF_SIZE,stdout);p1=buf; 111 | } 112 | *p1++=ch; 113 | } 114 | void print(int x){ 115 | static char s[15],*s1;s1=s; 116 | if (!x)*s1++='0';if (x<0)out('-'),x=-x; 117 | while(x)*s1++=x%10+'0',x/=10; 118 | while(s1--!=s)out(*s1); 119 | } 120 | void println(int x){ 121 | static char s[15],*s1;s1=s; 122 | if (!x)*s1++='0';if (x<0)out('-'),x=-x; 123 | while(x)*s1++=x%10+'0',x/=10; 124 | while(s1--!=s)out(*s1); out('\n'); 125 | } 126 | void print(ll x){ 127 | static char s[25],*s1;s1=s; 128 | if (!x)*s1++='0';if (x<0)out('-'),x=-x; 129 | while(x)*s1++=x%10+'0',x/=10; 130 | while(s1--!=s)out(*s1); 131 | } 132 | void println(ll x){ 133 | static char s[25],*s1;s1=s; 134 | if (!x)*s1++='0';if (x<0)out('-'),x=-x; 135 | while(x)*s1++=x%10+'0',x/=10; 136 | while(s1--!=s)out(*s1); out('\n'); 137 | } 138 | void print(double x,int y){ 139 | static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000, 140 | 1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL, 141 | 100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL}; 142 | if (x<-1e-12)out('-'),x=-x;x*=mul[y]; 143 | ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1; 144 | ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2); 145 | if (y>0){out('.'); for (size_t i=1;iwrite 166 | char Out[OUT_SIZE],*o=Out; 167 | inline void print1(int x){ 168 | static char buf[15]; 169 | char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x; 170 | while(x)*p1++=x%10+'0',x/=10; 171 | while(p1--!=buf)*o++=*p1; 172 | } 173 | inline void println1(int x){print1(x);*o++='\n';} 174 | inline void print1(ll x){ 175 | static char buf[25]; 176 | char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x; 177 | while(x)*p1++=x%10+'0',x/=10; 178 | while(p1--!=buf)*o++=*p1; 179 | } 180 | inline void println1(ll x){print1(x);*o++='\n';} 181 | inline void print1(char c){*o++=c;} 182 | inline void println1(char c){*o++=c;*o++='\n';} 183 | inline void print1(char *s){while (*s)*o++=*s++;} 184 | inline void println1(char *s){print1(s);*o++='\n';} 185 | inline void println1(){*o++='\n';} 186 | inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}} 187 | struct puts_write{ 188 | ~puts_write(){flush1();} 189 | }_puts; 190 | inline void print2(int x){printf("%d",x);} 191 | inline void println2(int x){printf("%d\n",x);} 192 | inline void print2(char x){printf("%c",x);} 193 | inline void println2(char x){printf("%c\n",x);} 194 | inline void print2(ll x){ 195 | #ifdef _WIN32 196 | printf("%I64d",x); 197 | #else 198 | #ifdef __linux 199 | printf("%lld",x); 200 | #else 201 | puts("error:can't recognize the system!"); 202 | #endif 203 | #endif 204 | } 205 | inline void println2(ll x){print2(x);printf("\n");} 206 | inline void println2(){printf("\n");} 207 | #undef ll 208 | #undef OUT_SIZE 209 | #undef BUF_SIZE 210 | }; 211 | using namespace fastIO; 212 | --------------------------------------------------------------------------------