Acm模板
walnut, purity, dreamcloud
目录
一、头部
1. #include <bits/stdc++.h>
2. /*int类型最大值INT_MAX,short最大值为SHORT_MAX
3. long long最大值为LONG_LONG_MAX*/
4. #define _clr(x,y) memset(x,y,sizeof(x))
5. #define _inf(x) memset(x,0x3f,sizeof(x))
6. #define pb push_back
7. #define mp make_pair
8. #define FORD(i,a,b) for (int i=(a); i<=(b); i++)
9. #define FORP(i,a,b) for (int i=(a); i>=(b); i--)
10. #define REP(i,n) for (int i=0; i<(n); i++)
11. using namespace std;
12. const int INF = 0x3f3f3f3f;
13. const double eps = 1e-8;
14. const double EULER = 0.577215664901532860;
15. const double PI = 3.1415926535897932384626;
16. const double E = 2.71828182845904523536028;
17.
18. typedef long long LL;
二、常用STL
配对:
typedef pair<LL,LL>P;
离散化的意思是只考虑数值之间的相对大小,节省空间和时间,提高算法效率。
sort(sub_a,sub_a+n);
int size=unique(sub_a,sub_a+n)-sub_a;//size为离散化后元素个数,unique函数去重
for(i=0;i<n;i++)
a[i]=lower_bound(sub_a,sub_a+size,a[i])-sub_a + 1;
去重:
sort(vec.begin(), vec.end());
vec.resize(unique(vec.begin(),vec.end()) - vec.begin());
LOWER_BOUND
lower_bound(sub_a,sub_a+size,a[i]) 返回第一个大于等于a[i]的值的pos
upper_bound(sub_a,sub_a+size,a[i]) 返回第一个大于a[i]的值的pos
1. LL aa[N];
2. struct Node
3. {
4. int v;
5. int order;
6. }a[N];
7. bool cmp(Node a, Node b)
8. {
9. return a.v < b.v;
10. }
11.
12. int main()
13. {
14. for (int i = 1; i <= n; i++) {
15. scanf("%d", &a[i].v);
16. a[i].order = i;
17. }
18. sort(a + 1, a + n + 1, cmp);
19. for (int i = 1; i <= n; i++) aa[a[i].order] = i;
20. }
优先队列
1. priority_queue<int, vector<int>, greater<int> > pq;
迭代器和遍历STL
1. map<int,int>::iterator it;
2. for(it = mp.begin(); it < mp.end(); it++){
3. cout << it.second() << endl;
4. }
5. int count = vec.size();
6. for(int i = 0; i < count; i++){
7. cout << vec[i] << endl;
8. }
next_permutation o(n)
1. void TestArray()
2. {
3. char chs[] = {'a', 'd', 'c', 'e', 'b'};
4. int count = sizeof(chs)/sizeof(char);
5.
6. next_permutation(chs+0, chs + count);
7.
8. printf("TestArray:\n");
9. for(int i = 0; i < count; i++) {
10. printf("%c ", chs[i]);
11. }
12.
13. printf("\n");
14. }
Bitset
见cww模板。
1. #include <bitset>
三、输入输出和头文件
头文件:
1. #include <iostream>
2. #pragma comment(linker, "/STACK:1024000000,1024000000")
3. #include <stdio.h>
4. #include <fstream>
5. #include <iomanip>
6. #include <cmath>
7. #include <string>
8. #include <string.h>
9. #include <sstream>
10. #include <cctype>
11. #include <climits>
12. #include <set>
13. #include <map>
14. #include <deque>
15. #include <queue>
16. #include <vector>
17. #include <iterator>
18. #include <algorithm>
19. #include <stack>
20. #include <functional>
21. /*int类型最大值INT_MAX,short最大值为SHORT_MAX
22. long long最大值为LONG_LONG_MAX*/
23. #define _clr(x,y) memset(x,y,sizeof(x))
24. #define _inf(x) memset(x,0x3f,sizeof(x))
25. #define pb push_back
26. #define mp make_pair
27. #define FORD(i,a,b) for (int i=(a); i<=(b); i++)
28. #define FORP(i,a,b) for (int i=(a); i>=(b); i--)
29. #define REP(i,n) for (int i=0; i<(n); i++)
30. using namespace std;
31. const int INF = 0x3f3f3f3f;
32. const double eps = 1e-8;
33. const double EULER = 0.577215664901532860;
34. const double PI = 3.1415926535897932384626;
35. const double E = 2.71828182845904523536028;
36.
37. typedef long long LL;
文件输入输出:
1. freopen("a.in","r",stdin);
2. freopen("a.out","w",stdout);
快速读:
1. struct FastIO
2. {
3. static const int S = 1310720;
4. int wpos;
5. char wbuf[S];
6. FastIO() : wpos(0) {}
7. inline int xchar()
8. {
9. static char buf[S];
10. static int len = 0, pos = 0;
11. if (pos == len)
12. pos = 0, len = fread(buf, 1, S, stdin);
13. if (pos == len) return -1;
14. return buf[pos ++];
15. }
16. inline LL Lint()
17. {
18. int c = xchar();
19. LL x = 0;
20. while (c <= 32) c = xchar();
21. for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
22. return x;
23. }
24. inline int xint()
25. {
26. int s = 1, c = xchar(), x = 0;
27. while (c <= 32) c = xchar();
28. if (c == '-') s = -1, c = xchar();
29. for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
30. return x * s;
31. }
32. inline void xstring(char *s)
33. {
34. int c = xchar();
35. while (c <= 32) c = xchar();
36. for (; c > 32; c = xchar()) * s++ = c;
37. *s = 0;
38. }
39. inline void wchar(int x)
40. {
41. if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
42. wbuf[wpos ++] = x;
43. }
44. inline void wint(LL x)
45. {
46. if (x < 0) wchar('-'), x = -x;
47. char s[24];
48. int n = 0;
49. while (x || !n) s[n ++] = '0' + x % 10, x /= 10;
50. while (n--) wchar(s[n]);
51. }
52. inline void wstring(const char *s)
53. {
54. while (*s) wchar(*s++);
55. }
56. ~FastIO()
57. {
58. if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
59. }
60. } io;
61. n = io.xint(), m = io.xint();
62.
cin加速:
1. std::ios::sync_with_stdio(false);
四、java高精度and大整数
Java.math包中,有BigInteger和BigDecimal两个类,分别可以表示长度不可变的,任意精度的整数和小数,并且可以和字符串相互转换,使得Java在处理大数方面具有独特的优势。
大整数
—:在java中的基本头文件(java中叫包)
import java.io.*
importjava.util.* 我们所用的输入scanner在这个包中
importjava.math.* 我们下面要用到的BigInteger就这这个包中
二:输入与输出
读入 Scanner cin=new Scanner(System.in)
While(cin.hasNext()) //相当于C语言中的!=EOF
String str =null;
str =cin.next();
n =cin.nextInt(); //输入一个int型整数
n =cin.nextBigInteger(); //输入一个大整数
System.out.print(n); //输出n但不换行
System.out.println(); //换行
System.out.println(n); //输出n并换行
System.out.printf(“%d\n”,n); //类似C语言中的输出
三:定义变量
定义单个变量:
int a,b,c; //和C++ 中无区别
BigInteger a; //定义大数变量a
BigIntegerb= new BigInteger("2"); //定义大数变量 b赋值为 2;
BigDecimaln; //定义大浮点数类 n;
定义数组:
int a[]= new int[10] //定义长度为10的数组a
BigInteger b[] =new BigInteger[100] //定义长度为100的数组a
四:表示范围
布尔型 boolean 1 true,falsefalse
字节型byte8 -128-1270
字符型char16 ‘\u000’-\uffff ‘\u0000’
短整型short16 -32768-327670
整型 int 32 -2147483648,21474836470
长整型long64 -9.22E18,9.22E180
浮点型 float 321.4E-45-3.4028E+380.0
双精度型 double 644.9E-324,1.7977E+3080.0
BigInteger任意大的数,原则上只要你的计算机内存足够大,可以有无限位
五:常用的一些操作
A=BigInteger.ONE; //把0赋给A
B=BigInteger.valueOf (3); //把3赋给B;
A[i]=BigInteger.valueOf (10); //把10赋给A[i]
c=a.add(b) //把a与b相加并赋给c
c=a.subtract(b) //把a与b相减并赋给c
c=a.multiply(b) //把a与b相乘并赋给c
c=a.divide(b) //把a与b相除并赋给c
c=a.mod(b) // 相当于a%b
a.pow(b) //相当于a^b
a.compareTo(b): //根据该数值是小于、等于、或大于a 返回 -1、0 或 1;
a.equals(b): //判断两数是否相等,也可以用compareTo来代替;
a.min(b),a.max(b): //取两个数的较小、大者;
六:例题hdu 5920 求回文数(大整数)
1. import java.math.*;
2. //import java.io.*;
3. import java.util.*;
4. public class big {
5. public static BigInteger fanzhuan(BigInteger n){
6. //System.out.println("fanzhuan" + n);
7. int k = String.valueOf(n).length();
8. BigInteger ret = BigInteger.ZERO;
9. for (int i=1;i<=k;i++){
10. ret = ret.add(n.mod(BigInteger.TEN));
11. ret = ret.multiply(BigInteger.TEN);
12. n = n.divide(BigInteger.TEN);
13. }
14. ret = ret.divide(BigInteger.TEN);
15. return ret;
16. }
17. public static void main(String[] argv){
18. Scanner cin = new Scanner(System.in);
19. int T =cin.nextInt();
20. for (int cas=1;cas<=T;cas++){
21. BigInteger n = cin.nextBigInteger();
22. int N = String.valueOf(n).length();
23. int A = 0;
24. BigInteger ans[] = new BigInteger[55];
25. for (;N>1;){
26. //System.out.println("n=" + n);
27. BigInteger one0 = BigInteger.TEN.pow(N>>1);
28. BigInteger half = n.divide(one0);
29. if (N<=2){
30. if (N==1){
31. ans[++A] = n;
32. n = BigInteger.ZERO;
33. break;
34. }else {//2 wei
35. if (n.compareTo(BigInteger.valueOf(19))==0){
36. ans[++A] = BigInteger.valueOf(11);
37. ans[++A] = BigInteger.valueOf( 8);
38. n = BigInteger.ZERO;
39. break;
40. }else if (n.compareTo(BigInteger.valueOf(19))==-1){
41. ans[++A] = BigInteger.valueOf(9);
42. ans[++A] = n.subtract(BigInteger.valueOf(9));
43. n = BigInteger.ZERO;
44. break;
45. }//else continue;
46. }
47. }
48. half = half.subtract(BigInteger.ONE);
49. //System.out.println("half=" + half);
50. BigInteger fan = fanzhuan(half);
51. if (N%2>0) fan = fan.mod(one0);
52. //System.out.println("fan=" + fan);
53. BigInteger jan = half.multiply(one0).add(fan);
54. //System.out.println("jan=" + jan);
55. ans[++A] = jan ;
56. n = n.subtract(jan);
57. N = String.valueOf(n).length();
58. }
59. if (n.compareTo(BigInteger.ZERO)==1)ans[++A] = n;
60. System.out.printf("Case #%d:\n%d\n",cas,A);
61. for (int i=1;i<=A;i++){
62. System.out.println(ans[i]);
63. }
64. }
65. cin.close();
66. }
67. }
高精度
(一)BigDecimal类的常用的几个构造方法
· BigDecimal(int):将int表示形式转换为BigDecimal对象
· BigDecimal(String) :将字符串表示形式转换为BigDecimal对象
· BigDecimal(double):将double表示形式转换为BigDecimal对象
(二)BigDecimal类的常用方法
· add(BigDecimal):BigDecimal对象中的值相加,返回BigDecimal对象
· subtract(BigDecimal):BigDecimal对象中的值相减,返回BigDecimal对象
· multiply(BigDecimal):BigDecimal对象中的值相乘,返回BigDecimal对象
· divide(BigDecimal):BigDecimal对象中的值相除,返回BigDecimal对象
· toString():将BigDecimal对象中的值转换成字符串
· doubleValue():将BigDecimal对象中的值转换成双精度数
· floatValue():将BigDecimal对象中的值转换成单精度数
· longValue():将BigDecimal对象中的值转换成长整数
· intValue():将BigDecimal对象中的值转换成整数
下面分享一个用于高精确处理常用的数学运算类
1. package com.per.test;
2.
3. import java.math.BigDecimal;
4.
5. /**
6. * 用于高精确处理常用的数学运算
7. * Created by lijuan on 2016/8/27.
8. */
9. public class ArithmeticUtils {
10. //默认除法运算精度
11. private static final int DEF_DIV_SCALE = 10;
12.
13. /**
14. * 提供精确的加法运算
15. *
16. * @param v1 被加数
17. * @param v2 加数
18. * @return 两个参数的和
19. */
20.
21. public static double add(double v1, double v2) {
22. BigDecimal b1 = new BigDecimal(Double.toString(v1));
23. BigDecimal b2 = new BigDecimal(Double.toString(v2));
24. return b1.add(b2).doubleValue();
25. }
26.
27. /**
28. * 提供精确的加法运算
29. *
30. * @param v1 被加数
31. * @param v2 加数
32. * @return 两个参数的和
33. */
34. public static BigDecimal add(String v1, String v2) {
35. BigDecimal b1 = new BigDecimal(v1);
36. BigDecimal b2 = new BigDecimal(v2);
37. return b1.add(b2);
38. }
39.
40. /**
41. * 提供精确的加法运算
42. *
43. * @param v1 被加数
44. * @param v2 加数
45. * @param scale 保留scale 位小数
46. * @return 两个参数的和
47. */
48. public static String add(String v1, String v2, int scale) {
49. if (scale < 0) {
50. throw new IllegalArgumentException(
51. "The scale must be a positive integer or zero");
52. }
53. BigDecimal b1 = new BigDecimal(v1);
54. BigDecimal b2 = new BigDecimal(v2);
55. return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
56. }
57.
58. /**
59. * 提供精确的减法运算
60. *
61. * @param v1 被减数
62. * @param v2 减数
63. * @return 两个参数的差
64. */
65. public static double sub(double v1, double v2) {
66. BigDecimal b1 = new BigDecimal(Double.toString(v1));
67. BigDecimal b2 = new BigDecimal(Double.toString(v2));
68. return b1.subtract(b2).doubleValue();
69. }
70.
71. /**
72. * 提供精确的减法运算。
73. *
74. * @param v1 被减数
75. * @param v2 减数
76. * @return 两个参数的差
77. */
78. public static BigDecimal sub(String v1, String v2) {
79. BigDecimal b1 = new BigDecimal(v1);
80. BigDecimal b2 = new BigDecimal(v2);
81. return b1.subtract(b2);
82. }
83.
84. /**
85. * 提供精确的减法运算
86. *
87. * @param v1 被减数
88. * @param v2 减数
89. * @param scale 保留scale 位小数
90. * @return 两个参数的差
91. */
92. public static String sub(String v1, String v2, int scale) {
93. if (scale < 0) {
94. throw new IllegalArgumentException(
95. "The scale must be a positive integer or zero");
96. }
97. BigDecimal b1 = new BigDecimal(v1);
98. BigDecimal b2 = new BigDecimal(v2);
99. return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
100. }
101.
102. /**
103. * 提供精确的乘法运算
104. *
105. * @param v1 被乘数
106. * @param v2 乘数
107. * @return 两个参数的积
108. */
109. public static double mul(double v1, double v2) {
110. BigDecimal b1 = new BigDecimal(Double.toString(v1));
111. BigDecimal b2 = new BigDecimal(Double.toString(v2));
112. return b1.multiply(b2).doubleValue();
113. }
114.
115. /**
116. * 提供精确的乘法运算
117. *
118. * @param v1 被乘数
119. * @param v2 乘数
120. * @return 两个参数的积
121. */
122. public static BigDecimal mul(String v1, String v2) {
123. BigDecimal b1 = new BigDecimal(v1);
124. BigDecimal b2 = new BigDecimal(v2);
125. return b1.multiply(b2);
126. }
127.
128.
129. /**
130. * 提供精确的乘法运算
131. *
132. * @param v1 被乘数
133. * @param v2 乘数
134. * @param scale 保留scale 位小数
135. * @return 两个参数的积
136. */
137. public static double mul(double v1, double v2, int scale) {
138. BigDecimal b1 = new BigDecimal(Double.toString(v1));
139. BigDecimal b2 = new BigDecimal(Double.toString(v2));
140. return round(b1.multiply(b2).doubleValue(), scale);
141. }
142.
143. /**
144. * 提供精确的乘法运算
145. *
146. * @param v1 被乘数
147. * @param v2 乘数
148. * @param scale 保留scale 位小数
149. * @return 两个参数的积
150. */
151. public static String mul(String v1, String v2, int scale) {
152. if (scale < 0) {
153. throw new IllegalArgumentException(
154. "The scale must be a positive integer or zero");
155. }
156. BigDecimal b1 = new BigDecimal(v1);
157. BigDecimal b2 = new BigDecimal(v2);
158. return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
159. }
160.
161. /**
162. * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
163. * 小数点以后10位,以后的数字四舍五入
164. *
165. * @param v1 被除数
166. * @param v2 除数
167. * @return 两个参数的商
168. */
169.
170. public static double div(double v1, double v2) {
171. return div(v1, v2, DEF_DIV_SCALE);
172. }
173.
174. /**
175. * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
176. * 定精度,以后的数字四舍五入
177. *
178. * @param v1 被除数
179. * @param v2 除数
180. * @param scale 表示表示需要精确到小数点以后几位。
181. * @return 两个参数的商
182. */
183. public static double div(double v1, double v2, int scale) {
184. if (scale < 0) {
185. throw new IllegalArgumentException("The scale must be a positive integer or zero");
186. }
187. BigDecimal b1 = new BigDecimal(Double.toString(v1));
188. BigDecimal b2 = new BigDecimal(Double.toString(v2));
189. return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
190. }
191.
192. /**
193. * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
194. * 定精度,以后的数字四舍五入
195. *
196. * @param v1 被除数
197. * @param v2 除数
198. * @param scale 表示需要精确到小数点以后几位
199. * @return 两个参数的商
200. */
201. public static String div(String v1, String v2, int scale) {
202. if (scale < 0) {
203. throw new IllegalArgumentException("The scale must be a positive integer or zero");
204. }
205. BigDecimal b1 = new BigDecimal(v1);
206. BigDecimal b2 = new BigDecimal(v1);
207. return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
208. }
209.
210. /**
211. * 提供精确的小数位四舍五入处理
212. *
213. * @param v 需要四舍五入的数字
214. * @param scale 小数点后保留几位
215. * @return 四舍五入后的结果
216. */
217. public static double round(double v, int scale) {
218. if (scale < 0) {
219. throw new IllegalArgumentException("The scale must be a positive integer or zero");
220. }
221. BigDecimal b = new BigDecimal(Double.toString(v));
222. return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
223. }
224.
225. /**
226. * 提供精确的小数位四舍五入处理
227. *
228. * @param v 需要四舍五入的数字
229. * @param scale 小数点后保留几位
230. * @return 四舍五入后的结果
231. */
232. public static String round(String v, int scale) {
233. if (scale < 0) {
234. throw new IllegalArgumentException(
235. "The scale must be a positive integer or zero");
236. }
237. BigDecimal b = new BigDecimal(v);
238. return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
239. }
240.
241.
242. /**
243. * 取余数
244. *
245. * @param v1 被除数
246. * @param v2 除数
247. * @param scale 小数点后保留几位
248. * @return 余数
249. */
250. public static String remainder(String v1, String v2, int scale) {
251. if (scale < 0) {
252. throw new IllegalArgumentException(
253. "The scale must be a positive integer or zero");
254. }
255. BigDecimal b1 = new BigDecimal(v1);
256. BigDecimal b2 = new BigDecimal(v2);
257. return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
258. }
259.
260. /**
261. * 取余数 BigDecimal
262. *
263. * @param v1 被除数
264. * @param v2 除数
265. * @param scale 小数点后保留几位
266. * @return 余数
267. */
268. public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
269. if (scale < 0) {
270. throw new IllegalArgumentException(
271. "The scale must be a positive integer or zero");
272. }
273. return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
274. }
275.
276. /**
277. * 比较大小
278. *
279. * @param v1 被比较数
280. * @param v2 比较数
281. * @return 如果v1 大于v2 则 返回true 否则false
282. */
283. public static boolean compare(String v1, String v2) {
284. BigDecimal b1 = new BigDecimal(v1);
285. BigDecimal b2 = new BigDecimal(v2);
286. int bj = b1.compareTo(b2);
287. boolean res;
288. if (bj > 0)
289. res = true;
290. else
291. res = false;
292. return res;
293. }
294. }
某次多校做的题
1. import java.math.BigDecimal;
2. import java.util.Scanner;
3.
4. public class Main {
5.
6. public static void main(String[] args) {
7. String x1, y1, x2, y2, x3, y3, tx, ty;
8. //BigDecimal
9. String cx, cy;
10. Scanner in = new Scanner(System.in);
11. int t;
12. t = in.nextInt();
13. while((t--) > 0) {
14. x1 = in.next();
15. y1 = in.next();
16. x2 = in.next();
17. y2 = in.next();
18. x3 = in.next();
19. y3 = in.next();
20. tx = in.next();
21. ty = in.next();
22. // point 1
23. BigDecimal a1 = new BigDecimal(x1);
24. BigDecimal b1 = new BigDecimal(y1);
25. BigDecimal c1 = new BigDecimal("1");
26. BigDecimal ta1 = a1.multiply(a1);
27. BigDecimal tb1 = b1.multiply(b1);
28. BigDecimal tp1 = ta1.add(tb1);
29. BigDecimal d1 = tp1.multiply(new BigDecimal(-1));
30. // point 2
31. BigDecimal a2 = new BigDecimal(x2);
32. BigDecimal b2 = new BigDecimal(y2);
33. BigDecimal c2 = new BigDecimal("1");
34. BigDecimal ta2 = a2.multiply(a2);
35. BigDecimal tb2 = b2.multiply(b2);
36. BigDecimal tp2 = ta2.add(tb2);
37. BigDecimal d2 = tp2.multiply(new BigDecimal(-1));
38. // point 3
39. BigDecimal a3 = new BigDecimal(x3);
40. BigDecimal b3 = new BigDecimal(y3);
41. BigDecimal c3 = new BigDecimal("1");
42. BigDecimal ta3 = a3.multiply(a3);
43. BigDecimal tb3 = b3.multiply(b3);
44. BigDecimal tp3 = ta3.add(tb3);
45. BigDecimal d3 = tp3.multiply(new BigDecimal(-1));
46. BigDecimal g1 = d1.multiply(c2).subtract(d2.multiply(c1));
47. BigDecimal g2 = b2.multiply(c3).subtract(b3.multiply(c2));
48. BigDecimal g3 = d2.multiply(c3).subtract(d3.multiply(c2));//(d2*c3-d3*c2)
49. BigDecimal g4 = b1.multiply(c2).subtract(b2.multiply(c1));//(b1*c2-b2*c1)
50.
51. BigDecimal g5 = a1.multiply(c2).subtract(a2.multiply(c1));//(a1*c2-a2*c1)
52. BigDecimal g6 = b2.multiply(c3).subtract(b3.multiply(c2));//(b2*c3-b3*c2)
53.
54. BigDecimal g7 = a2.multiply(c3).subtract(a3.multiply(c2));//(a2*c3-a3*c2)
55. BigDecimal g8 = b1.multiply(c2).subtract(b2.multiply(c1));//(b1*c2-b2*c1)
56.
57. g1 = g1.multiply(g2).subtract(g3.multiply(g4));
58. g2 = g5.multiply(g6).subtract(g7.multiply(g8));
59. BigDecimal x = g1.divide(g2);
60.
61.
62. //yyyyyyyyyyyyyyyy
63. BigDecimal gg1 = d1.multiply(c2).subtract(d2.multiply(c1));
64. BigDecimal gg2 = a2.multiply(c3).subtract(a3.multiply(c2));
65. BigDecimal gg3 = d2.multiply(c3).subtract(d3.multiply(c2));
66. BigDecimal gg4 = a1.multiply(c2).subtract(a2.multiply(c1));
67. BigDecimal gg5 = a2.multiply(c3).subtract(a3.multiply(c2));
68. BigDecimal gg6 = b1.multiply(c2).subtract(b2.multiply(c1));
69. BigDecimal gg7 = a1.multiply(c2).subtract(a2.multiply(c1));
70. BigDecimal gg8 = b2.multiply(c3).subtract(b3.multiply(c2));
71.
72. BigDecimal y = (gg1.multiply(gg2).subtract(gg3.multiply(gg4))).divide(gg5.multiply(gg6).subtract(gg7.multiply(gg8)));
73.
74. //zzzzzzzzzzzzzzzzz
75. BigDecimal z = d1.subtract(a1.multiply(x)).subtract(b1.multiply(y)).divide(c1);
76. System.out.println(x.toString());
77. System.out.println(y.toString());
78. System.out.println(z.toString());
79.
80. BigDecimal btx = new BigDecimal(tx);
81. BigDecimal bty = new BigDecimal(ty);
82. BigDecimal btx2 = btx.multiply(btx);
83. BigDecimal bty2 = bty.multiply(bty);
84. BigDecimal oth = btx2.add(bty2).add(z);
85.
86. BigDecimal didi = btx.multiply(x);
87. BigDecimal eiei = bty.multiply(y);
88.
89. oth = oth.add(didi).add(eiei);
90. if(oth.compareTo(new BigDecimal("0")) <= 0) {
91. System.out.println("Rejected");
92. }
93. else System.out.println("Accepted");
94. }
95. }
96. }
五、树状数组
修改(查询)某点的值,区间求和(区间更新),O(N*M)(区间长度N,M次操作),树状数组的话就是O(NlogM)
模板:
1. int lowbit(int k)
2. {
3. return k & (-k);
4. }
5. void add(int k,int x)
6. {
7. while(k <= n){
8. c[k] += x;
9. k += lowbit(k);
10. }
11. }
12. int getsum(int k)
13. {
14. int sum = 0;
15. while(k > 0){
16. sum += c[k];
17. k -= lowbit(k);
18. }
19. return sum;
20. }
例题:求逆序对。(poj2299)
1. #include <cstdio>
2. #include <iostream>
3. #include <cstring>
4. #include <algorithm>
5. using namespace std;
6. typedef long long LL;
7. #define FOR(i, a, b) for(LL i = (a); i <(b); ++i)
8. const LL N = (LL)1e6 + 7;
9. int c[N], n, aa[N];
10. struct Node
11. {
12. int v;
13. int order;
14. }a[N];
15.
16. bool cmp(Node a, Node b)
17. {
18. return a.v < b.v;
19. }
20. int lowbit(int k)
21. {
22. return k & (-k);
23. }
24. void add(int k,int x)
25. {
26. while(k <= n){
27. c[k] += x;
28. k += lowbit(k);
29. }
30. }
31. int getsum(int k)
32. {
33. int sum = 0;
34. while(k > 0){
35. sum += c[k];
36. k -= lowbit(k);
37. }
38. return sum;
39. }
40.
41. int main()
42. {
43. while(~scanf("%d", &n), n){
44. LL ans = 0;
45. memset(c, 0, sizeof(c));
46. for (int i = 1; i <= n; i++) {
47. scanf("%d", &a[i].v);
48. a[i].order = i;
49. }
50. sort(a + 1, a + n + 1, cmp);
51. for (int i = 1; i <= n; i++)
52. aa[a[i].order] = i;
53. for(int i = 1; i <= n; i++){
54. add(aa[i], 1);
55. ans += i - getsum(aa[i]);//统计当前序列中大于a的元素的个数
56. }
57. printf("%lld\n", ans);
58. }
59. return 0;
60. }
六、并查集
1. void init(int n){ //初始化函数
2. for(int i=0;i<=n;i++)fa[i]=i;
3. }
4.
5. int find(int x){ //寻找祖宗
6. return fa[x]==x?x:fa(x)=find(fa[x]);
7. }
8.
9. void union(int x,int y){ //合并两点
10. int dx=find(x),dy=find(y);
11. if(dx!=dy)fa[dx]=dy;
12. }
七、数论
欧拉函数
1. LL euler(LL x){
2. if(x<2){
3. return 0;
4. }
5. int ans=1;
6. for(int i=2; i*i<=x; i++){
7. if(x%i==0){
8. ans*=i-1;
9. x/=i;
10. }
11. while(x%i==0){
12. x/=i;
13. ans*=i;
14. }
15. }
16. if(x>1){
17. ans*=x-1;
18. }
19. return ans;
20. }
莫比乌斯函数
1. void Init(){
2. memset(vis,0,sizeof(vis));
3. mu[1] = 1;
4. cnt = 0;
5. for(int i=2; i<N; i++){
6. if(!vis[i]){
7. prime[cnt++] = i;
8. mu[i] = -1;
9. }
10. for(int j=0; j<cnt&&i*prime[j]<N; j++){
11. vis[i*prime[j]] = 1;
12. if(i%prime[j]) mu[i*prime[j]] = -mu[i];
13. else{
14. mu[i*prime[j]] = 0;
15. break;
16. }
17. }
18. }
19. }
欧拉筛
1. #include <cstring>
2. using namespace std;
3. int prime[1100000], primesize, phi[11000000];
4. bool isprime[11000000];
5. void getlist(int listsize){
6. memset(isprime, 1, sizeof(isprime));
7. isprime[1] = false;
8. for(int i = 2;i <= listsize; i++){
9. if(isprime[i]) prime[++primesize] = i;
10. for(int j = 1; j <= primesize && i * prime[j] <= listsize; j++){
11. isprime[i*prime[j]] = false;
12. if(i % prime[j] == 0) break;
13. }
14. }
15. }
快速幂
1. #include <bits/stdc++.h>
2. using namespace std;
3. typedef long long LL;
4. LL fast_multi(LL m, LL n, LL mod){//快速乘法
5. LL ans = 0;//注意初始化是 0,不是 1
6. for( ;n; n >>= 1){
7. if (n & 1) ans += m;
8. m = (m + m) % mod;//和快速幂一样,只不过这里是加
9. m %= mod;//取模,不要超出范围
10. ans %= mod;
11. }
12. return ans;
13. }
14. LL fast_pow(LL a, LL n, LL mod){//快速幂
15. LL ans = 1;
16. for(;n;n >>= 1){
17. if (n & 1) ans = fast_multi(ans, a, mod);//不能直接乘
18. a = fast_multi(a, a, mod);
19. ans %= mod;
20. a %= mod; `
21. }
22. return ans;
23. }
24. int main(){
25. cout << fast_multi(2, 3, 10) << endl;
26. }
乘法逆元
欧几里得算法
1. #include <cstdio>
2.
3. int gcd(int a, int b){
4. return a % b ? gcd(b, a % b) : b;
5. }
6. void exGcd(int a,int b,int &x,int &y){
7. if(b==0){
8. x=1;y=0;
9. return ;
10. }
11. exGcd(b,a%b,x,y);
12. int temp;
13. temp=y;
14. y=x-a/b*y;
15. x=temp;
16. }
17. int main(){
18. int m, n;
19. int x,y;
20. while(~scanf("%d%d", &m, &n)){
21. exGcd(m, n, x, y);
22. printf("%d %d %d\n", gcd(m, n), x, y);
23. }
24. return 0;
25. }
八、动态规划
LIS(最长上升子序列)
1. int lis()
2. {
3. memset(dp, 0, sizeof(dp));
4. int Max;
5. for (int i = 0; i < n; ++i)
6. {
7. Max = 0;
8. for (int j = 0; j < i; ++j)
9. {
10. if (a[i] > a[j])
11. {
12. Max = max(Max, dp[j]);
13. }
14. }
15. dp[i] = Max + 1;
16. }
17. Max = 0;
18. for (int i = 0; i < n; ++i)
19. {
20. if (dp[i] > Max) Max = dp[i];
21. }
22. return Max;
23. }
1. int lis()
2. {
3. memset(dp, 0, sizeof(int)*n);
4. int len = 1;
5. dp[0] = a[0];
6. for (int i = 1; i < n; ++i)
7. {
8. int pos = lower_bound(dp, dp + len, a[i]) - dp;
9. dp[pos] = a[i];
10. len = max(len, pos + 1);
11. }
12. return len;
13. }
LCS(最长公共子序列)
1. public static int lcs(String str1, String str2) {
2. int len1 = str1.length();
3. int len2 = str2.length();
4. int c[][] = new int[len1+1][len2+1];
5. for (int i = 0; i <= len1; i++) {
6. for( int j = 0; j <= len2; j++) {
7. if(i == 0 || j == 0) {
8. c[i][j] = 0;
9. } else if (str1.charAt(i-1) == str2.charAt(j-1)) {
10. c[i][j] = c[i-1][j-1] + 1;
11. } else {
12. c[i][j] = max(c[i - 1][j], c[i][j - 1]);
13. }
14. }
15. }
16. return c[len1][len2];
17. }
最长公共子串
1. public static int lcs(String str1, String str2) {
2. int len1 = str1.length();
3. int len2 = str2.length();
4. int result = 0; //记录最长公共子串长度
5. int c[][] = new int[len1+1][len2+1];
6. for (int i = 0; i <= len1; i++) {
7. for( int j = 0; j <= len2; j++) {
8. if(i == 0 || j == 0) {
9. c[i][j] = 0;
10. } else if (str1.charAt(i-1) == str2.charAt(j-1)) {
11. c[i][j] = c[i-1][j-1] + 1;
12. result = max(c[i][j], result);
13. } else {
14. c[i][j] = 0;
15. }
16. }
17. }
18. return result;
19. }
背包问题
1. #include<stdio.h>
2. #include<iostream>
3. #include<cstring>
4. using namespace std;
5.
6. int main(){
7. int t, n, M, w[30], p[30], dp[100005] = {-1};
8. cin >> t;
9. while(t--){
10. memset(dp,0,sizeof(dp));
11. // cout << dp[10] << endl;
12. cin >> n >> M;
13. for( int i = 0; i < n; i++ )
14. cin >> w[i] >> p[i];
15. for( int i = 0; i < n; i++ )
16. {
17. //因为使用了一维数组,所有j要按照递减顺序
18. for( int j = M; j >= w[i]; j-- )
19. {
20. if( dp[j-w[i]] + p[i] > dp[j] )
21. dp[j] = dp[j-w[i]] + p[i];
22. }
23. }
24. cout << dp[M] << endl;
25. }
26. }
九、线段树
模板一
1. #include <cstdio>
2. #include <iostream>
3.
4. using namespace std;
5. #define lson l, m, rt << 1
6. #define rson m + 1, r, rt << 1 | 1
7. const int maxn = 55555;
8. int sum[maxn << 2];
9. void PushUP(int rt){
10. sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
11. }
12. void build(int l, int r, int rt){
13. if(l == r){
14. scanf("%d", &sum[rt]);
15. return ;
16. }
17. int m = (l + r) >> 1;
18. build(lson);
19. build(rson);
20. PushUP(rt);
21. }
22. void update(int p, int add, int l, int r, int rt){
23. if(l == r) {
24. sum[rt] += add;
25. return ;
26. }
27. int m = (l + r) >> 1;
28. if(p <= m) update(p, add, lson);
29. else update(p, add, rson);
30. PushUP(rt);
31. }
32. int query(int L, int R, int l, int r, int rt){
33. if(L <= l && r <= R) return sum[rt];
34. int m = (l + r) >> 1;
35. int ret = 0;
36. if(L <= m) ret += query(L, R, lson);
37. if(R > m) ret += query(L, R, rson);
38. return ret;
39. }
40. int main(){
41. int t, n;
42. scanf("%d", &t);
43. for(int cas = 1; cas <= t; cas ++){
44. cout << "Case " << cas << ":" << endl;
45. scanf("%d", &n);
46. build(1, n, 1);
47. char op[10];
48. while(scanf("%s", op)){
49. if(op[0] == 'E') break;
50. int a, b;
51. scanf("%d%d", &a, &b);
52. if(op[0] == 'Q') cout << query(a, b, 1, n, 1) << endl;
53. else if(op[0] == 'S') update(a, -b, 1, n, 1);
54. else update(a, b, 1, n, 1);
55. }
56. }
57. }
模板二
1. const int maxn = 100010;
2. int n, m, note, a, b;
3. struct Segment_Tree{
4. int l, r, x;
5. bool flag;
6. }segTree[maxn * 4 + 10];
7.
8. void build(int note, int be, int en){
9.
10. segTree[note].l = be;
11. segTree[note].r = en;
12. if(be == en)return;
13. build(2 * note, be, (be + en) / 2);
14. build(2 * note + 1, (be + en) / 2 + 1, en);
15.
16. }
17. void pushup(int x){
18. segTree[x].x = segTree[x * 2].x + segTree[x * 2 + 1].x;
19. }
20. void pushdown(int x){
21. if(segTree[x].flag){
22. segTree[x].flag = 0;
23. if(segTree[x].l < segTree[x].r){
24. segTree[x * 2].flag ^= 1;
25. segTree[x * 2 + 1].flag ^= 1;
26. }
27. segTree[x].x = segTree[x].r - segTree[x].l + 1 - segTree[x].x;
28. }
29. }
30. void add(int note, int a, int b){
31. if(segTree[note].l == a && segTree[note].r == b){
32. segTree[note].flag ^= 1;
33. pushdown(note);
34. return ;
35. }
36. pushdown(note);
37. int mid = (segTree[note].l + segTree[note].r) / 2;
38. if(b <= mid) add(note * 2, a, b), pushdown(note * 2 + 1);
39. else if(a > mid) add(note * 2 + 1, a, b), pushdown(note * 2);
40. else add(note * 2, a, mid), add(note * 2 + 1, mid + 1, b);
41. pushup(note);
42. }
43.
44. int query(int note, int a, int b){
45. pushdown(note);
46. if(segTree[note].l == a && segTree[note].r == b)
47. return segTree[note].x;
48. int mid = (segTree[note].l + segTree[note].r) / 2;
49. if(b <= mid) return query(note * 2, a, b);
50. else if(a > mid) return query(note * 2 + 1, a, b);
51. else return query(note * 2, a, mid) + query(note * 2 + 1, mid + 1, b);
52. }
53.
54. int main(){
55. scanf("%d%d", &n, &m);
56. build(1, 1, n);
57. for(int i = 0; i < m; i++){
58. scanf("%d%d%d", ¬e, &a, &b);
59. if(note == 0)
60. add(1, a, b);
61. else
62. cout << query(1, a, b) << endl;
63. }
64. }
十、字符串
KMP算法
1. void getNext()
2. {
3. int i=0,j=-1;
4. next_[0]=-1;
5. while(i<m)
6. {
7. if(pattern[i]==pattern[j] || j==-1)
8. {
9. i++,j++;
10. if(pattern[i]!=pattern[j])
11. next_[i]=j;
12. else
13. next_[i]=next_[j];
14. }
15. else
16. j=next_[j];
17. }
18. }
19.
20.
21. void findNext()
22. {
23. int i=0,j=0;
24. while(i<n && j<m)
25. if(pattern[j]==text[i] || j==-1)
26. i++,j++;
27. else
28. j=next_[j];
29. if(j==m)
30. printf("%d\n",i-m+1);
31. else
32. printf("-1\n");
33. }
Trie树
1. Trie树
2. #include <iostream>
3. #include <cstdio>
4. #include <cstdlib>
5. #include <cstring>
6. #include <algorithm>
7. #include <iomanip>
8.
9. using namespace std;
10.
11. int num;//字符串的总个数
12.
13. struct Trie
14. {
15. int cnt;//某个字符串出现的总个数
16. char name[30];//保存的字符串
17. bool ok;//是不是走到了字符串的最后一个字母,保存最后一个字母的那个节点也保存着整个字符串的Name
18. Trie *next[127];//子节点,ASCII最大值为126
19. Trie()
20. {
21. ok=0;
22. cnt=0;
23. for(int i=0;i<127;i++)
24. next[i]=NULL;
25. }
26. }root;
27.
28. void create(char s[])
29. {
30. int len=strlen(s);
31. Trie*p=&root;
32. for(int i=0;i<len;i++)
33. {
34. int id=s[i];
35. if(p->next[id]==NULL)
36. p->next[id]=new Trie;
37. p=p->next[id];
38. }
39. p->cnt++;//走到字符串的最后一个字母的节点
40. strcpy(p->name,s);
41. p->ok=1;
42. }
43.
44. void dfs(Trie *root)//递归输出
45. {
46. Trie*p=root;
47. if(p->ok)
48. cout<<p->name<<" "<<setiosflags(ios::fixed)<<setprecision(4)<<100.0*p->cnt/num<<endl;
49. for(int i=0;i<127;i++){
50. if(p->next[i]!=NULL){
51. dfs(p->next[i]);
52. }
53. }
54. }
55.
56. char s[30];
57.
58. int main()
59. {
60.
61. while(gets(s)){
62. create(s);
63. num++;
64. }
65. dfs(&root);
66. return 0;
67. }
十一、图论
Floyd
1. #include <iostream>
2. #include <cstdio>
3. #include <cstring>
4. #include <map>
5. using namespace std;
6. const int INF = 0x3f3f3f3f;
7. int n;
8. double cost, e[110][110];
9. string s1, s2;
10. int m;
11. map<string, int> mp;
12.
13. void Folyd()
14. {
15. for(int k = 1; k <= n; k++)
16. for(int i = 1; i <= n; i++)
17. for(int j = 1; j <= n; j++)
18. {
19. if(e[i][j] > e[i][k] + e[k][j]) //松弛操作
20. e[i][j] = e[i][k] + e[k][j];
21. }
22.
23. }
24. void init()
25. {
26. for(int i = 1; i <= n; i++)
27. for(int j = 1; j <= n; j++)
28. {
29. if(i == j)
30. e[i][j] = 0;
31. else
32. e[i][j] = INF;
33. }
34. }
35. int main(){
36. scanf("%d%d", &n, &m);
37. init();
38. int cas = 1;
39. for(int i = 0; i < m; i++){
40. cin >> s1 >> s2 >> cost;
41. if(mp[s1] == 0)mp[s1] = cas++;
42. if(mp[s2] == 0)mp[s2] = cas++;
43. e[mp[s2]][mp[s1]] = e[mp[s1]][mp[s2]] = cost;
44. }
45. Folyd();
46. int t;
47. scanf("%d", &t);
48. for(int i = 0; i < t; i++){
49. cin >> s1 >> s2;
50. if(e[mp[s1]][mp[s2]] < INF && mp[s1] && mp[s2]) cout << e[mp[s1]][mp[s2]] << endl;
51. else cout << "-1" << endl;
52. }
53. }
DIJ迪杰斯特拉
1. #include <iostream>
2. using namespace std;
3.
4. const int maxnum = 100;
5. const int maxint = 999999;
6.
7.
8. void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
9. {
10. bool s[maxnum]; // 判断是否已存入该点到S集合中
11. for(int i=1; i<=n; ++i)
12. {
13. dist[i] = c[v][i];
14. s[i] = 0; // 初始都未用过该点
15. if(dist[i] == maxint)
16. prev[i] = 0;
17. else
18. prev[i] = v;
19. }
20. dist[v] = 0;
21. s[v] = 1;
22.
23. // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
24. // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
25. for(int i=2; i<=n; ++i)
26. {
27. int tmp = maxint;
28. int u = v;
29. // 找出当前未使用的点j的dist[j]最小值
30. for(int j=1; j<=n; ++j)
31. if((!s[j]) && dist[j]<tmp)
32. {
33. u = j; // u保存当前邻接点中距离最小的点的号码
34. tmp = dist[j];
35. }
36. s[u] = 1; // 表示u点已存入S集合中
37.
38. // 更新dist
39. for(int j=1; j<=n; ++j)
40. if((!s[j]) && c[u][j]<maxint)
41. {
42. int newdist = dist[u] + c[u][j];
43. if(newdist < dist[j])
44. {
45. dist[j] = newdist;
46. prev[j] = u;
47. }
48. }
49. }
50. }
51.
52. void searchPath(int *prev,int v, int u)
53. {
54. int que[maxnum];
55. int tot = 1;
56. que[tot] = u;
57. tot++;
58. int tmp = prev[u];
59. while(tmp != v)
60. {
61. que[tot] = tmp;
62. tot++;
63. tmp = prev[tmp];
64. }
65. que[tot] = v;
66. for(int i=tot; i>=1; --i)
67. if(i != 1)
68. cout << que[i] << " -> ";
69. else
70. cout << que[i] << endl;
71. }
72.
73. int main()
74. {
75. freopen("input.txt", "r", stdin);
76. // 各数组都从下标1开始
77. int dist[maxnum]; // 表示当前点到源点的最短路径长度
78. int prev[maxnum]; // 记录当前点的前一个结点
79. int c[maxnum][maxnum]; // 记录图的两点间路径长度
80. int n, line; // 图的结点数和路径数
81.
82. // 输入结点数
83. cin >> n;
84. // 输入路径数
85. cin >> line;
86. int p, q, len; // 输入p, q两点及其路径长度
87.
88. // 初始化c[][]为maxint
89. for(int i=1; i<=n; ++i)
90. for(int j=1; j<=n; ++j)
91. c[i][j] = maxint;
92.
93. for(int i=1; i<=line; ++i)
94. {
95. cin >> p >> q >> len;
96. if(len < c[p][q]) // 有重边
97. {
98. c[p][q] = len; // p指向q
99. c[q][p] = len; // q指向p,这样表示无向图
100. }
101. }
102.
103. for(int i=1; i<=n; ++i)
104. dist[i] = maxint;
105. for(int i=1; i<=n; ++i)
106. {
107. for(int j=1; j<=n; ++j)
108. printf("%8d", c[i][j]);
109. printf("/n");
110. }
111.
112. Dijkstra(n, 1, dist, prev, c);
113.
114. // 最短路径长度
115. cout << "源点到最后一个顶点的最短路径长度: " << dist[n] << endl;
116.
117. // 路径
118. cout << "源点到最后一个顶点的路径为: ";
119. searchPath(prev, 1, n);
120. }
最小生成树
1. 最小生成树prim
2. #include <iostream>
3. #include <cstdio>
4. #include <cmath>
5. #include <cstring>
6. using namespace std;
7. int n, m, x, y;
8. double cost, e[1005][1005], mincost[1005];
9. bool vis[1005];
10. struct node{
11. int x, y;
12. }v[1005];
13. const int INF = 0x3f3f3f3f;
14.
15. double prim(){
16. double sum = 0;
17. while(1){
18. int vv;
19. double mn = INF;
20. for(int i = 1; i <= n; i++){
21. if(!vis[i] && mn > mincost[i]) {
22. vv = i;
23. mn = mincost[i];
24. //cout << mn << endl;
25. }
26. }
27. if(mn == INF)break;
28. sum += mn;
29. vis[vv] = true;
30. // cout << vv << endl;
31. for(int i = 1; i <= n; i++){
32. if(mincost[i] > e[vv][i]){
33. mincost[i] = e[vv][i];
34. }
35. }
36. }
37. return sum;
38. }
39. int main(){
40. for(int i = 0; i < 1005; i++){
41. mincost[i] = INF;
42. }
43. memset(vis, false, sizeof(vis));
44. mincost[1] = 0;
45. scanf("%d%d", &n, &m);
46. for(int i = 1; i <= n; i++){
47. scanf("%d%d", &v[i].x, &v[i].y);
48. for(int j = 1; j < i; j++){
49. cost = sqrt((double)(v[i].x - v[j].x) * (v[i].x - v[j].x)
50. + (double)(v[i].y - v[j].y) * (v[i].y - v[j].y));
51. e[i][j] = e[j][i] = cost;
52. }
53. }
54. for(int i = 0; i < m; i++){
55. scanf("%d%d", &x, &y);
56. e[x][y] = e[y][x] = 0;
57. }
58. // cout << mincost[2] << endl;
59. printf("%.2f\n", prim());
60. return 0;
61. }
十二、网络流
匈牙利算法,最小点覆盖(最大匹配数)二分图匹配
1. #include <iostream>
2. #include <cstdio>
3. #include <algorithm>
4. #include <cstring>
5. using namespace std;
6. int n, m, a, b, nx, ny;
7. bool g[510][510], used[510];
8. int link[510];
9. bool dfs (int u) {
10. for (int v = 1; v <= ny; v++) {
11. if (!used[v] && g[u][v]) {
12. used[v] = true;
13. if (link[v] == -1 || dfs (link[v])) {
14. link[v] = u;
15. return true;
16. }
17. }
18. }
19. return false;
20. }
21. int maxmatch () {
22. int res = 0;
23. memset (link, -1, sizeof (link));//link[i]=-1表示i不在匹配中,否则(link[i],i)这条边在匹配中
24. for (int i = 1; i <= nx; i++) {
25. memset (used, false, sizeof (used));
26. if (dfs (i)) res++;
27. }
28. return res;
29. }
30.
31. int main(){
32. scanf("%d%d", &n, &m);
33. nx = ny = n;
34. memset(g, false, sizeof(g));
35. for(int i = 0; i < m; i++){
36. scanf("%d%d", &a, &b);
37. g[a][b] = true;
38. }
39. cout << maxmatch() << endl;
40.
41. }
网络流
见挑战
十三、树
哈夫曼树(二叉搜索树)
1. 哈夫曼树(二叉搜索树)
2. oj
3. #include <iostream>
4. #include <cstdio>
5.
6. using namespace std;
7.
8. int dp[210][210], sum[210][210], a[210],b[210];;
9. int n;
10.
11. int main()
12. {
13. while(~scanf("%d", &n), n){
14. for(int i = 1;i <= n; ++i)
15. scanf("%d", &a[i]);
16. for(int i = 0; i <= n; ++i)
17. scanf("%d", &b[i]);
18. for(int i = 1; i <= n; ++i)
19. sum[i][i] = a[i] + b[i] + b[i-1];
20. for(int d = 1; d < n; ++d)
21. for(int i = 1; i+d <= n; ++i)
22. sum[i][i+d] = sum[i][i+d-1] + a[i+d] + b[i+d];
23. for(int i = 1;i <= n+1; ++i){
24. sum[i][i-1] = b[i-1];
25. dp[i][i-1] = 0;
26. }
27. for(int d = 0; d < n; ++d)
28. for(int i = 1; i+d <= n; ++i){
29. int j = i + d;
30. int mx = 1000000000;
31. for(int k = i; k <= j;++k)
32. mx = min(mx, dp[i][k-1] + dp[k+1][j]);
33. dp[i][j] = mx + sum[i][j];
34. }
35. cout << dp[1][n] << endl;
36. }
37. return 0;
38. }
39.
40. 作业
41. 问题一:二叉搜索树的建立和中序遍历
42. 思路:
43. 本题首先考虑如何从文件中输入和输出,于是想到了输入输出的重定向。
44. 另外就是二叉搜索树的建立,即考虑插入元素的算法。
45. 递归实现中序遍历。
46.
47. #include <stdio.h>
48. #include <stdlib.h>
49. #include <fstream>
50. typedef int Elemtype;
51.
52. typedef struct BiTNode{
53. Elemtype data;
54. struct BiTNode *lchild, *rchild;
55. }BiTNode, *BiTree;
56.
57. //在给定的BST中插入结点,其数据域为element
58. int BSTInsert( BiTree *t, Elemtype element )
59. {
60. if( NULL == *t ) {
61. (*t) = (BiTree)malloc(sizeof(BiTNode));
62. (*t)->data = element;
63. (*t)->lchild = (*t)->rchild = NULL;
64. return 1;
65. }
66.
67. if( element == (*t)->data )
68. return 0;
69.
70. if( element < (*t)->data )
71. return BSTInsert( &(*t)->lchild, element );
72.
73. return BSTInsert( &(*t)->rchild, element );
74. }
75.
76. //创建BST
77. void CreateBST( BiTree *t, Elemtype *a, int n )
78. {
79. (*t) = NULL;
80. for( int i=0; i<n; i++ )
81. BSTInsert( t, a[i] );
82. }
83.
84. //中序遍历打印BST
85. void PrintBST(BiTree t)
86. {
87. if( t ) {
88. PrintBST( t->lchild );
89. printf("%d\n", t->data);
90. PrintBST( t->rchild );
91. }
92. }
93.
94. int main()
95. {
96. freopen("C:/Users/dellpc/Desktop/data1w.txt","r",stdin); //输入输出重定向
97. freopen("C:/Users/dellpc/Desktop/out.txt","w",stdout);
98. int n;
99. int *a;
100. BiTree t;
101. scanf("%d", &n);
102. a = (int *)malloc(sizeof(int)*n); //申请空间
103. for( int i=0; i<n; i++ )
104. scanf("%d", &a[i]);
105. CreateBST(&t, a, n);
106. PrintBST(t);
107. return 0;
108. }
十四、矩阵连乘
1. 矩阵连乘
2. #include <iostream>
3. #include<algorithm>
4. #include<cstring>
5. using namespace std;
6.
7. typedef long long ll;
8.
9. ll a[55],b[55],mul[55][55];
10.
11. int main()
12. {
13. int N;
14. cin >> N;
15. //cout << ans << endl;
16. while(N--){
17. int n,j;
18. ll tmp;
19. cin >> n;
20. for(int i = 0; i < n; i++)
21. cin >> a[i] >> b[i];
22. memset( mul , 0x7f, sizeof( mul ) );
23. // cout << mul[0][0] << endl;
24. for (int i = 0; i < n; ++i )
25. mul[ i ][ i ] = 0;
26. for (int len = 1; len < n; ++len )
27. for (int i = 0; i + len < n; ++i ) {
28. j = i + len;
29. for (int k = i + 1; k <= j; ++k ) {
30. tmp = mul [ i ][ k - 1 ] + mul [ k ][ j ] + a[ i ] * a[ k ] * b[ j ];
31. if ( mul [ i ][ j ] > tmp )
32. mul [ i ][ j ] = tmp;
33. }
34. }
35. cout << mul[0][n - 1] << endl;
36. }
37. return 0;
38. }
39.
十五、分治法
最近点对
1. 最近点对
2.
3. #include <iostream>
4. #include<stdio.h>
5. #include<math.h>
6. #include<stdlib.h>
7. #include<cstdlib>
8. #include<cstring>
9. #include<algorithm>
10. using namespace std;
11.
12. int n;
13. struct node{
14. double x,y;
15. }N[100010];
16.
17. int cmpx(node a, node b){
18. return a.x<b.x;
19. }
20. double dis(struct node a,struct node b){
21. return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
22. }
23. double closest(int low,int high){
24. if(low + 1 == high)
25. return dis(N[low],N[high]);
26. if(low + 2 == high)
27. return min(dis(N[low] , N[high]) , min( dis(N[low] , N[low+1]) , dis(N[low+1] , N[high]) ));
28. int mid = (low + high)>>1;
29.
30. double ans = min( closest(low , mid) , closest(mid + 1 , high) );
31. double sum = dis(N[0],N[1]);
32. for(int i=low;i<=mid;i++){
33. for(int j=mid+1;j<=high;j++){
34. if((N[j].x-N[i].x)>ans)break;
35. sum = min(sum,dis(N[i],N[j]));
36. }
37. }
38. ans = min(ans,sum);
39. return ans;
40. }
41. int main()
42. {
43. while(scanf("%d",&n),n){
44. for(int i = 0; i < n; i++){
45. scanf("%lf%lf",&N[i].x,&N[i].y);
46. }
47. sort(N,N+n,cmpx);
48. printf("%.2f\n",closest(0,n-1)/2);
49. }
50. return 0;
51. }
十六、凸包
1. 最小凸包
2. #include <cstdio>
3. #include <iostream>
4. #include <stack>
5. #include <cmath>
6. #include <cstdlib>
7. using namespace std;
8. #define pi 3.1415926
9. struct NODE{
10. double x, y;
11. }node[1010], result[1010];
12. int n, top;
13. double line, dis, my, mx;
14. int p;
15. double eps = 1e-10;
16. stack<NODE> st;
17. double Distance(NODE p1,NODE p2) //两点间的距离
18. {
19. return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
20. }
21. double Multiply(NODE p1,NODE p2,NODE p3) //叉积
22. {
23. return ((p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x));
24. }
25. int Compare(const void *p1,const void *p2) //根据p0->p1的极值和p0->p2的极值进行比较,如果极值相同则用距离长度比较
26. {
27. NODE *p3,*p4;
28. double m;
29. p3=(NODE *)p1;
30. p4=(NODE *)p2;
31. m = Multiply(node[0],*p3,*p4) ;
32. if(m<0) return 1;
33. else if(m < eps && (Distance(node[0],*p3) > Distance(node[0],*p4)))
34. return 1;
35. else return -1;
36. }
37. void GRAHAMSCAN()
38. {
39. result[0].x=node[0].x;
40. result[0].y=node[0].y;
41. result[1].x=node[1].x;
42. result[1].y=node[1].y;
43. result[2].x=node[2].x;
44. result[2].y=node[2].y;
45. top = 2;
46. for(int i=3;i<n;i++)
47. {
48. while(Multiply(result[top-1],result[top],node[i])<0 && top >= 2) {
49. top--;
50. }
51.
52. result[top+1].x=node[i].x;
53. result[top+1].y=node[i].y;
54. top++;
55. }
56. }
57.
58. int main(){
59. while(~scanf("%d", &n)){
60. dis = 0;
61. scanf("%lf", &line);
62. for(int i = 0; i < n; i++){
63. scanf("%lf%lf", &node[i].x, &node[i].y);
64. if(node[i].y < my || (fabs(node[i].y - my) < eps && node[i].x < mx) || i == 0){
65. p = i;
66. my = node[i].y;
67. mx = node[i].x;
68. }
69. }
70.
71. double temp=node[0].x;
72. node[0].x=node[p].x;
73. node[p].x=temp;
74. temp = node[0].y;
75. node[0].y = node[p].y;
76. node[p].y = temp;
77. qsort(&node[1],n-1,sizeof(double)*2,Compare);
78.
79. // for(int i = 0; i < n; i++)cout << node[i].x << " " << node[i].y << endl;
80.
81.
82. GRAHAMSCAN();
83. // cout << top << endl;
84. for(int i=0;i< top ;i++) {
85. // cout << result[i].x << " " << result[i].y << endl;
86. dis=dis+Distance(result[i],result[i+1]);
87. }
88. dis+= Distance(result[top] , node[0]);
89. //cout << dis << endl;
90. double s = pi * line * 2;
91. printf("%.0f\n", dis + s);
92. }
93. }
十七、解题思路
二分答案+判断(贪心)