算法板子

线段树 区间最大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]);

	}
}
![](https://img2024.cnblogs.com/blog/3323923/202504/3323923-20250422093411591-1381905164.png)


![](https://img2024.cnblogs.com/blog/3323923/202504/3323923-20250422093426691-29935662.png)


混合背包
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);
posted @ 2025-04-21 19:14  LteShuai  阅读(47)  评论(0)    收藏  举报