数学(二分,交点,快速米,找子串)
组合数+快速幂
int kmp(int a,int k)
{
int ans=1;
while (k)
{
if(k&1) ans=ans*a%mod;
k>>=1;
a=a*a%mod;
}
return ans;
} // 快速幂
///这个是预处理,全部算出来,进行多次询问
int fct[N], inv[N];///inv是分母,fct是1到i的一段乘
void init(int n)
{
fct[0]=1,inv[0]=ksm(1,mod-2);
for (int i=1;i<=n;i++) {
fct[i]=fct[i-1]*i%mod;
inv[i]=ksm(fct[i],mod-2); ///逆元算除法,既可以乘
}
}
int C(int a,int b)
{
if (b>a) return 0;
return fct[a]*inv[b]%mod*inv[a-b]%mod; ///到a的一段除以b在除以a-b这一段多余的
}
///下面是当你不多次询问,问一次算一次的写法
int C(int a, int b) ///a是下标,b是上标
{
int res = 1;
for (int i = 1, j = a; i <= b; i ++, j -- )
{
res = (int)res * j % mod;
res = (int)res * ksm(i, mod - 2) % mod;
}
return res;
}
int lucas(int a, int b) {
if (a < mod && b < mod) return C(a, b);
return (int) C(a % mod, b % mod) * lucas(a / mod, b / mod) % mod;
}
二分(整数+浮点数)
整数:
int l=0,r=1e9;
int ans;
while (l<=r)
{
int mid=(l+r)>>1;
if(ch(mid)) l=mid+1,ans=mid; ///具体跑区间转换具体题看
else r=mid-1;
}
浮点数:
bool check(double x) {/* ... */} // 检查x是否满足某种性质
double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
二维前缀和
S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
二维差分
给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
正式代码,得出的a就是进行区间加减后的结果
for(int i=1;i+k-1<=n;i++) {
for (int j = 1; j + k - 1 <= m; j++) {
a[i][j] += 1;
a[i + k][j + k] += 1;
a[i + k][j] -= 1;
a[i][j + k] -= 1;
}
}
for(int i=1;i<=n;i++) {
for (int j = 1; j <= m; j++) {
a[i][j] += (a[i][j - 1] + a[i - 1][j] - a[i - 1][j - 1]);
}
}
离散化
#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=3e6+7,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=100003;
typedef pair<int,int> PII;
vector<PII> a;
vector<PII> b;
vector<int> all;
int ans[N];
int s[N];
int n,m;
int find(int x)
{
int l,r;
l=0,r=all.size()-1;
while (l<r)
{
int mid=(l+r)/2;
if(all[mid]>=x) r=mid;
else l=mid+1;
}
return r+1;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int c,x;
cin>>x>>c;
a.push_back({x,c});
all.push_back(x);
}
for(int i=1;i<=m;i++)
{
int l,r;
cin>>l>>r;
b.push_back({l,r});
all.push_back(l);
all.push_back(r);
}
sort(all.begin(),all.end());
all.erase(unique(all.begin(),all.end()),all.end());
for(auto i:a)
{
int x= find(i.first);
ans[x]+=i.second;
}
for(int i=1;i<=all.size();i++)
{
s[i]=s[i-1]+ans[i];
}
for(auto i:b)
{
cout<<s[find(i.second)]-s[find(i.first)-1]<<endl;
}
}
signed main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int T=1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
二分图,匈牙利每一个数找对应最优数
vector<int> a[N]; ///根据题目要求 int vis[N]; ///标记这个点符合条件,但是没有匹配成功 int zhan[N]; ///谁占用了当下元素 bool dis(int x) { for(auto i:a[x]) { if(vis[i]) continue; vis[i]=1; if(!zhan[i] || dis(zhan[i])) ///判断占用这个点的东西能不能不占用这个点换一个目标 { zhan[i]=x; return 1; } } return 0; } 记得更新vis for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); ///记得初始化,因为每次都需要对要求点扫描一下 if(!dis(i)) ans++; }
最长上升子序列
vector<int> f(N,INF); int ma=-1; for(int i=1;i<=n;i++) { int id= lower_bound(f.begin(),f.end(),a[i])-f.begin(); f[id]=a[i]; ma=max(ma,id+1); }
o拉筛(质数)
vector<int> prime; bool st[N]; void pr(int n) { st[1]= true; for(int i=2;i<=n;i++) { if(!st[i]) prime.push_back(i); for(int j:prime) { if(j*i>n) break; st[j*i] = true; if(i%j==0) break; } } }
线段和线段直接求交点
1.求两直线的交点(两点式)
Point p1,p2,p3,p4;//对应的四个点,根据实际应用场景赋值 double a1, a2, a3, b1, b2, b3; double t; Point pp1, pp2; a1 = p4.y - p3.y; a2 = p3.y - p1.y; a3 = p2.y - p1.y; b1 = p4.x - p3.x; b2 = p3.x - p1.x; b3 = p2.x - p1.x; t = (a3 * b2 - a2 * b3) / (a1 * b3 - a3 * b1); pp1.x = (p4.x - p3.x) * t + p3.x; pp1.y = (p4.y - p3.y) * t + p3.y;
2.求两直线的交点(斜截式)
Point p1,p2;//对应的两个点,根据实际应用场景赋值 vector<Point> points;//用来拟合直线的点 Vec4f line; fitLine(points, line, DIST_L2, 0, 0.01, 0.01);//拟合得到直线,具体求解根据实际情况 double cos_theta = line[0]; double sin_theta = line[1]; double x0 = line[2], y0 = line[3]; double k = sin_theta / cos_theta; double b = y0 - k * x0; t = (k * p1.x + b - p1.y) / (p2.y - p1.y - k * (p2.x - p1.x)); Point pp1; pp1.x = (p2.x - p1.x) * t + p1.x; pp1.y = (p2.y - p1.y) * t + p1.y;
3.求垂足(两点式)
Point p1,p2;//对应的两个点,根据实际应用场景赋值 int a = p2.x - p1.x; int b = p2.y - p1.y; double t = (a * (p1.y - p3.y) + b * (p3.x - p1.x)); t = t / (a * a + b * b);//分两步计算,直接一步实现会由于精度问题导致结果出错 Point p; p.x = -b * t + p3.x; p.y = a * t + p3.y;
4.求垂足(斜截式)
Point p3;//直线外一点 vector<Point> points;//用来拟合直线的点 Vec4f pline; fitLine(points, pline, DIST_L2, 0, 0.01, 0.01); cos_theta = pline[0]; sin_theta = pline[1]; x0 = pline[2], y0 = pline[3]; double k1 = sin_theta / cos_theta; double b1 = y0 - k1 * x0; double b2 = 0; double k2 = -1 / k1; b2 = p3.y - k2 * p3.x ; pp1.x = (b2 - b1) / (k1 - k2); pp1.y = k2 * pp1.x + b2;

浙公网安备 33010602011771号