这两天一直在补cf的题解,没啥时间写(。。。其实是我出去玩了一天,orz)
所以水一下,把一些比较实用的模板复习一下。
gcd(辗转相除法循环实现)
int gcd(int a, int b) // a,b谁大谁小无所谓,可以为0 0 { while (b) { int temp = a % b; a = b; b = temp; } return a; }
快速幂运算(循环实现)
int power(int a, int n) { int ans = 1; while (n) { if (n % 2)//奇数时结算,并且补一个a ans *= a; a *= a; n /= 2; } return ans; }
二分,三分情况比较多,模板不是固定的
二分适用于查找单调区间,三分适用于查找凸性数据
hdu 2899 http://acm.hdu.edu.cn/showproblem.php?pid=2899
凸函数而且导数单调,所以二分三分都能做。
二分就是导数单调,所以用二分查找极值点,然后代入函数求值。
凸函数的话一般直接三分查找极值
二分的代码:
//二分做法 #include <bits/stdc++.h> using namespace std; int power(int a, int n) { int ans = 1; while (n) { if (n % 2) ans *= a; a *= a; n /= 2; } return ans; } double fun(double x) { return 42 * pow(x, 6) + 48 * pow(x, 5) + 21 * pow(x, 2) + 10 * x; } double f(double x, double y) { return 6 * pow(x, 7) + 8 * pow(x, 6) + 7 * pow(x, 3) + 5 * pow(x, 2) - y * x; } int main() { int t; scanf("%d", &t); while (t--) { double y; scanf("%lf", &y); double l = 0, r = 100; while (r - l > 1e-6)//注意适当精度即可 { double mid = (l + r) / 2; double ans = fun(mid); if (ans < y) { l = mid + 1e-7; } else r = mid - 1e-7; } printf("%.4lf\n", f(l, y)); } }
三分的代码:
//三分查找 #include <bits/stdc++.h> using namespace std; double f(double x, double y) { return 6 * pow(x, 7) + 8 * pow(x, 6) + 7 * pow(x, 3) + 5 * pow(x, 2) - y * x; } int main() { int t; scanf("%d", &t); while (t--) { double y; scanf("%lf", &y); double l = 0, r = 100; while (r - l > 1e-6) { double LeftThird = (l * 2 + r) / 3, RightThird = (l + r * 2) / 3; if (f(LeftThird, y) < f(RightThird, y)) { r = RightThird - 1e-7; } else l = LeftThird + 1e-7; } printf("%.4lf\n", f((l + r) / 2, y)); } }