算法板子
线段树 区间最大gcd 点修 差分
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int range=2e5+10;
int n;
int m;
int a[range];
int b[range];
int op;
int x,y,k;
#define lc u<<1
#define rc u<<1|1
int read()
{
int s=0;
char ch=getchar();
while(ch>='0'&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
// cout<<s<<endl;
return s;
}
void write(int x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
struct tree{
int l,r;
int sum,d;
}tr[4*range];
int gcd(int a,int b)
{
if(b)return gcd(b,a%b);
else return a;
}
void pushup(tree &u,tree l ,tree r)
{
u.sum=l.sum+r.sum;
u.d=gcd(l.d,r.d);
}
void build(int u,int l,int r)
{
tr[u]={l,r,b[l],b[l]};
if(l==r)return ;
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(tr[u],tr[lc],tr[rc]);
}
tree query(int u,int l,int r)
{
// cout<<u<<" "<<l<<" "<<r<<endl;
if(l<=tr[u].l&&r>=tr[u].r)
{
return tr[u];
}
int mid=tr[u].l+tr[u].r>>1;
if(r<=mid)return query(lc,l,r);
if(l>mid)return query(rc,l,r);
tree t;
pushup(t,query(lc,l,r),query(rc,l,r));
return t;
}
void solve()
{
// n=read();
// m=read();
scanf("%lld",&n);
scanf("%lld",&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
{
b[i]=a[i]-a[i-1];
}
build(1,1,n);
for(int i=1;i<=m;i++)
{
// char c;
// cin>>c;
// if(c=='C')
// {
// cin>>x>>y>>k;
// change(1,x,k);
// if(y+1<=n) change(1,y+1,-k);
//
// }
// else {
scanf("%lld",&x);
scanf("%lld",&y);
// cin>>x>>y;
tree b=query(1,1,x);
tree bb={0,0,0,0};
if(x+1<=y) bb=query(1,x+1,y);
// if(x+1<=n)????6666666
// cout<<bb.d<<endl;
printf("%lld\n",abs(gcd(b.sum,bb.d)));
// }
}
//+k shuchu gcd
return ;
}
signed main()
{
solve();
}
//2 5 // 1-10
//区间修改 改成点修
// if(l<=tr[u].l&&r>=tr[u].r)
// {
// tr[u].sum+=
//
// }
//void change(int u,int l,int k)
//{
// if(tr[u].l==tr[u].r){
// tr[u].sum+=k;
// tr[u].d+=k;
// return ;
// }
// int mid=tr[u].l+tr[u].r>>1;
// if(l<=mid)change(lc,l,k);
// if(l>mid)change(rc,l,k);
// pushup(tr[u],tr[lc],tr[rc]);
//}
随机二叉树的生成
#include <iostream>
#include <queue>
using namespace std;
// 定义一个结构体来表示二叉树的节点
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int value) : val(value), left(nullptr), right(nullptr) {}
};
// 用于打印边的函数
void printEdges(TreeNode* root) {
if (!root) return;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
if (node->left) {
cout << node->val << " " << node->left->val << endl;
q.push(node->left);
}
if (node->right) {
cout << node->val << " " << node->right->val << endl;
q.push(node->right);
}
}
}
// 创建一个包含 n 个节点的二叉树
TreeNode* generateTree(int n) {
if (n == 0) return nullptr;
TreeNode* root = new TreeNode(1);
queue<TreeNode*> q;
q.push(root);
int currentNodeValue = 2;
while (!q.empty() && currentNodeValue <= n) {
TreeNode* node = q.front();
q.pop();
if (currentNodeValue <= n) {
node->left = new TreeNode(currentNodeValue++);
q.push(node->left);
}
if (currentNodeValue <= n) {
node->right = new TreeNode(currentNodeValue++);
q.push(node->right);
}
}
return root;
}
int main() {
int n = 1000; // 总节点数
TreeNode* root = generateTree(n);
// 打印所有边
printEdges(root);
return 0;
}
随机n个数的生成 不重复
//#include <iostream>
//#include <set>
//#include <cstdlib>
//#include <ctime>
//
//using namespace std;
//
//int main() {
// // 初始化随机数种子
// srand(time(0));
//
// set<int> uniqueNumbers;
// int count = 0;
//
// // 生成 100 个不重复的数字
// while (count < 100) {
// int num = rand() % 1000 + 1; // 生成 1 到 1000 的随机数
// // 如果数字不重复,插入到 set 中
// if (uniqueNumbers.insert(num).second) {
// count++;
// }
// }
//
// // 输出生成的 100 个不重复的数字
// for (int num : uniqueNumbers) {
// cout << num << " ";
// }
// cout << endl;
//
// return 0;
//}
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
// 初始化随机数种子
srand(time(0));
set<int> uniqueNumbers;
// 生成 100 个不重复的数字
while (uniqueNumbers.size() < 100) {
int num = rand() % 1000 + 1; // 生成 1 到 1000 的随机数
uniqueNumbers.insert(num); // 插入 set 中,保证唯一性
}
// 将 set 中的数字复制到 vector 中
vector<int> numbers(uniqueNumbers.begin(), uniqueNumbers.end());
// 使用 std::shuffle 来随机打乱 vector 的顺序
random_shuffle(numbers.begin(), numbers.end());
// 输出随机顺序的 100 个不重复的数字
for (int num : numbers) {
cout << num << " ";
}
cout << endl;
return 0;
}
欧拉定理 欧拉线性筛 P2568 GCD
bool isprime[range];
int prime[range];
int phi[range];
int cnt;
int sum[range];
void euler()
{
//m*sk1=pj*i i有所有的质因子
// memset(isprime,true,sizeof isprime);
isprime[1]=1;
//
for(int i=2;i<=n;i++)
{
if(!isprime[i])
{
// cout<<"ss"<<i<<endl;
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
{
isprime[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=prime[j]*phi[i];
break;
}
else {
//fa(pj*i)=fa(m )
phi[i*prime[j]]=(prime[j]-1)*phi[i];
}
}
}
}
void solve()
{
cin>>n;
phi[1]=1;
//很重要 别漏了
euler();
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+phi[i];
}
int ans=0;
for(int i=1;i<=cnt&&prime[i]<=n;i++)
{
ans+=sum[n/prime[i]]*2-1;
}
cout<<ans<<endl;
return ;
}
模板 快速或 快速与 快速异或 O1的板子
#include <bits/stdc++.h>
using namespace std;
int getor(int l, int r)
{
if (l == r) return l;
return l | ((1 << ( __lg(l ^ r) + 1)) - 1);
}
int getand(int l, int r)
{
if (l == r) return l;
return l & (~((1 << (__lg(l ^ r) + 1)) - 1));
}
int getxor(int x)
{
if (x < 0) return 0;
if (x % 4 == 0) return x;
if (x % 4 == 1) return 1;
if (x % 4 == 2) return x + 1;
if (x % 4 == 3) return 0;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n, m;
scanf("%d %d", &n, &m);
int l=max(n-m,0);
int r=n+m;
printf("%d\n", getor(l, r));
}
}
x转10进制
#include <bits/stdc++.h>
using namespace std;
int x, a[105]; // 输入x进制
string S;
// char转数码
int charToInt(char c) {
if('0'<=c&&c<='9') return c-'0';
return c-'A'+10;
}
void solve(int x) {
cin>>S;
int len=S.size();
for(int i=len-1;i>=0;i--)
a[len-1-i]=charToInt(S[i]);
int ans=0,w=1;
for(int i=0;i<len+1;i++){
ans+=w*a[i];
w*=x;
}
cout<<ans<<endl;
}
int main()
{
int t;
t=5;
solve(4);solve(10);solve(2);solve(8);solve(16);
}
DFS判断环数 环 板子
int vis[N],pre[N];
vector<int>e[N];
void dfs(int u,int fa){ //dfs
vis[u] = 1;
for(auto v : e[u]){
if(v==fa) continue; //如果是无向的 a-->b 的同时也有 b-->a,所以直接排除另外的一种情况
if(vis[v]==0){ //如果没有访问就标记当前元素的前一个元素
pre[v] = u;
dfs(v,u); //并且一直递归访问下去
}else if(vis[v]==1){
bool flag=0;
int temp = u,cnt = 1;//环的长度
if(temp==1||v==1)flag=1;
while(temp != v)
{
if(temp==1)flag=1;
// cout<<temp<<" ";
cnt++;
temp =pre[temp];
}
// cout<<v<<"\n";
if(flag)
nums=min(nums,cnt);
}
}
vis[u] = 2;
}
signed main()
{
int n,m;int u,v;
//n为点数 m为边数 u是起点v是终点
cin >> n>>m;
for(int i = 1;i <= m;i++){
cin >> u >> v;
e[u].push_back(v);
// e[v].push_back(u);
}
for(int i = 1;i <= n;i++){ //可能是非联通图
if(vis[i]==0) //每一次可以访问完和该点相连的所有点
dfs(i,-1);
}
if(nums==1e15){
cout<<-1<<endl;return 0;
}
cout << nums << endl; //环数
}
lucas
int mod;
int jc[range];
int qpow(int a,int n)
{
int ans=1;
// a=a%mod;
while(n){
if(n&1)
ans=ans*a%mod;
a=a*a%mod;
n>>=1;
}
return ans%mod;
}
int inv(int x){
return qpow(x,mod-2)%mod;
}
int C(int x,int m)
{
if(m>x){
// cout<<x<<" "<<m<<endl;
return 0;
}
int g=(((jc[x]%mod*inv(jc[x-m])%mod)%mod)*inv(jc[m])%mod)%mod;
return g%mod;
}
int lucas(int n,int m)
{
if(m==0)return 1;
return ((lucas(n/mod,m/mod)%mod)*(C(n%mod,m%mod)%mod))%mod;
}
void solve(int t)
{
int x,y;
cin>>x>>y>>mod;
jc[0]=1;
for(int i=1;i<=100010;i++){
jc[i]=jc[i-1]*i%mod;
}
cout<<lucas(x+y,x)%mod<<endl;
}
对拍
#include<bits/stdc++.h>
#define int long long
#define debug cout<<endl<<"--------"<<endl;
using namespace std;
const int range=2e3+10;
int n;int m;
int a[range];
int x;
int b[range];
int c[range];
int d[range];
int k;
char ma[100][100];
int num[100][100];
char s[4]={'l','d','u','r'};
void solve()
{
int t =1;
srand(time(0));
// while(t--)
// {
// int n;
// n=rand()%(2)+4;
// cout<<n<<endl;
// m=rand()%(2)+3;
// int w=4;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// ma[i][j]=s[rand()%(4)];
// }
// }
// int maxn=n*m;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// num[i][j]=rand()%(2)+1;
//// num[i][j]=1;
// }
// }
// cout<<n<<" "<<m<<endl;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++){
// cout<<ma[i][j];
// }
// cout<<endl;
// }for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++){
// cout<<num[i][j]<<" ";
// }
// cout<<endl;
// }
// cout<<endl;
// }
n=rand()%(10)+1;
// k=rand()%(n)+1;
for(int i=1;i<=n;i++)
{
a[i]=rand()%(100)+1;
}
cout<<n<<endl;
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
/*
0~32767
要取得 [a,b) 的随机整数,使用 (rand() % (b-a))+ a;
要取得 [a,b] 的随机整数,使用 (rand() % (b-a+1))+ a;
要取得 (a,b] 的随机整数,使用 (rand() % (b-a))+ a + 1;
通用公式: a + rand() % n;其中的 a 是起始值,n 是整数的范围。
*/
// n=(rand()%(50))+1;
//// m=rand()%(30000+1);
// x=(rand()%(50))+1;
// m=(rand()%(10000))+1;
// for(int i=1;i<=n;i++){
// a[i]=(rand()%(30))+1;
// b[i]=(rand()%(1000))+1;
// c[i]=(rand()%(30))+1;
// d[i]=(rand()%(1000))+1;
// }
// cout<<n<<" "<<x<<" "<<m<<endl;
// for(int i=1;i<=n;i++)cout<<a[i]<<" "<<b[i]<<" "<<c[i]<<" "<<d[i]<<endl;
return ;
}
signed main()
{
solve();
}
//#include<bits/stdc++.h>
//using namespace std;
//
//int main() {
// // 输入n
// srand(time(0));
// int n;
//// std::cout << "Enter a number n: ";
//// std::cin >> n;
// n=(rand()%(10))+1;
// // 创建一个从1到n的序列
// std::vector<int> arr(n);
// for (int i = 0; i < n; ++i) {
// arr[i] = i + 1; // 填充1到n
// }
//
// // 创建随机引擎
// std::random_device rd; // 获取一个随机种子
// std::mt19937 g(rd()); // 通过随机设备初始化梅森旋转算法的随机引擎
//
// // 使用std::shuffle进行随机排列
// std::shuffle(arr.begin(), arr.end(), g);
//
// // 输出随机排列
//// std::cout << "Random permutation: ";
// std::cout<<n<<std::endl;
// for (int i = 0; i < n; ++i) {
// std::cout << arr[i] << " ";
// }
// std::cout << std::endl;
//
// return 0;
//}
#include <bits/stdc++.h>
using namespace std;
int main() {
int t = 0;
while (true) {
cout << "test:" << t++ << endl;
system("data.exe > data.in");
system("std.exe < data.in > std.out");
system("solve.exe < data.in > solve.out");
if (system("fc std.out solve.out > diff.log")) {
cout << "WA\n";
break;
}
cout << "AC\n";
}
}
//
distance
#include <iostream>
#include <set>
#include <iterator> // for std::distance
int main() {
// 创建一个multiset
std::multiset<int> s = {10, 20, 30, 40, 50, 50, 60};
// 查找数组中的每个元素在multiset中的下界
int a[] = {10, 25, 50, 70};
int n = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < n; ++i) {
// 使用lower_bound找到第一个不小于a[i]的元素
auto it = std::lower_bound(s.begin(), s.end(), a[i]);
if (it != s.end()) {
// 使用std::distance计算从s.begin()到it的距离
auto d = std::distance(s.begin(), it);
std::cout << "Element " << a[i] << " lower bound at position " << d << std::endl;
} else {
std::cout << "Element " << a[i] << " has no lower bound in the multiset" << std::endl;
}
}
return 0;
}
筛法求约数和
include<bits/stdc++.h>
define int long long
define endl '\n'
using namespace std;
const int range=2e5+10;
int n;
int a[range];
bool isprime[range];
int prime[range];
int cnt;
int g[range];
int f[range];
void euler()
{
f[1]=g[1]=1;
isprime[1]=1;
for(int i=2;i*i<=range;i++)
{
if(!isprime[i])
{
prime[++cnt]=i;
g[i]=f[i]=i+1;
}
for(int j=1;j<=cnt&&prime[j]*i<=range;j++)
{
int m=i*prime[j];
isprime[m]=1;
if(i%prime[j]==0)
{
g[m]=g[i]*prime[j]+1;
f[m]=f[i]/g[i]*g[m];
break;
}
else {
g[m]=prime[j]+1;
f[m]=f[i]*g[m];
}
}
}
}
卡特兰数
include<bits/stdc++.h>
define int long long
define endl '\n'
using namespace std;
const int range=2e5+10;
int n;
int f[range];
void solve()
{
//
// f[0]=1;
// cin>>n;
// cout<<4n-2<<" "<<n+1<<endl;
// for(int i=1;i<=n;i++)
// {
// f[i]=f[i-1](4i-2);
// cout<<f[i]<<endl;
// f[i]%=100;
// }
// cout<<f[n]<<endl;
f[0]=f[1]=1;
cin>>n;
for(int i=2;i<=n;++i)
for(int j=1;j<=i;++j)
{
f[i]+=f[j-1]f[i-j];
f[i]%=100;
}
std::printf("%d",f[n]);
//
}
二维前缀和
for(int i=1;i<=5001;i++)
{
for(int j=1;j<=5001;j++)
{
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
}
}
for(int i=m;i<=5001;i++)
{
for(int j=m;j<=5001;j++)
{
res=max(res,sum[i][j]-sum[i-m][j]-sum[i][j-m]+sum[i-m][j-m]);
}
}


混合背包
cin>>n>>m;
int num=0;
for(int i=1;i<=n;i++){
cin>>v>>w>>s;
if(s==0)
{ //完全背包
a[++num]=v;
b[num]=w;
c[num]=0;
}
else {
if(s==-1)//01背包转多重背包
s=1;
int k=1;
while(s>=k){
a[++num]=k*v;
b[num]=k*w;
c[num++]=1;//背包类型 //变多重背包
s-=k;
k<<=1;
}
}
if(s)
{
a[++num]=s*v;
b[num]=s*w;
c[num]=1;
}
}
for(int i=1;i<=num;i++)
{
if(c[i]==1)
{
for(int j=m;j>=a[i];j--)
{
f[j]=max(f[j],f[j-a[i]]+b[i]);
}
}
else {
for(int j=a[i];j<=m;j++)
{
f[j]=max(f[j],f[j-a[i]]+b[i]);
}
}
}
cout<<f[m];
双向链表
include <bits/stdc++.h>
using namespace std;
define int long long
int n;
int op = -1e9 - 1;
int ed = 1e9 + 1;
int ll, rr;
int a, b;
map<int,bool>vis;
map<int, int>l, r;
signed main() {
cin >> n;
r[op] = 1;
l[ed] = 1;
r[1] = ed;
l[1] = op;
// 编号为2---n的同学
for (int i = 2; i <= n; i++) {
cin >> a >> b;
if (b == 1) { //右边 a同学的右边
rr = r[a];
r[i] = rr;
r[a] = i;
l[i] = a;
l[rr] = i;
} else { //表示插在左边
ll = l[a];
r[ll] = i;
l[i] = ll;
l[a] = i;
r[i] = a;
}
}
int m;
cin >> m;
int x;
for (int i = 1; i <= m; i++) {
cin >> x;
if(vis[x])continue;
//...a b c d..--
// ... a d ..
//此时来个b就出事了 相当于又把b连接了
vis[x]=1;
ll = l[x];
rr = r[x];
r[ll] = rr;
l[rr] = ll;
}
for (int i = r[op]; i != ed; i = r[i]) {
// if(vis[i]==0)
cout << i << " ";
}
return 0;
}
逆序对
void merge(int l,int r)
{
if(l>=r)return ;
int i=l;int k=l,mid=l+r>>1,j=mid+1;
merge(l,mid);
merge(mid+1,r);
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])b[k++]=a[i++];
else b[k++]=a[j++],ans+=mid-i+1;
}//我比你大,但是排名你比我大 这就是逆序对
while(i<=mid)b[k++]=a[i++];
while(j<=r)b[k++]=a[j++];
for( i=l;i<=r;i++)a[i]=b[i];
return ;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
merge(0,n-1);

浙公网安备 33010602011771号