蓝桥杯前最后的挣扎(雾

①P2831 愤怒的小鸟

涉及到计算几何的(其实是数学)的搜索,做法可以搜索或者状压,但我都不会QAQ

搜索时首先考虑是否能与之前生成的二次曲线相交,若可以则直接往下搜

否则考虑与之前的孤立点建立曲线,删除孤立点后继续搜索(记得回溯)

最后在将该点加入孤立点,供后续的点用于构造曲线,然后再搜索


#include<bits/stdc++.h>
#define ll long long
#define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
double pi = acos(-1);
const double eps = 1e-6;
const int maxn = 1e6 + 10;
const int inf = 1e9;

int n, m;

struct Point {
	double x, y;
}p[20];

inline int dcmp(double x)//cmp x with 0
{
	if (fabs(x) <= eps)return 0;
	return x < 0 ? -1 : 1;
}
inline int cmp(double x, double y)
{
	//x>y return 1
	//x<y reutrn -1
	//x==y return 0
	return dcmp(x - y);
}

double lina[20], linb[20], apx[20], apy[20];

int ans;

bool check(int p, double x, double y)
{
	if (cmp(lina[p] * pow(x, 2) + linb[p] * x, y) == 0)
		return 1;
	return 0;
}

void dele(int p,int LIM)
{
	for (int i = p; i <= LIM; i++)
		apx[i] = apx[i + 1], apy[i] = apy[i + 1];
}

void repla(int p, int LIM, double x,double y)
{
	for (int i = LIM; i > p; i--)
		apx[i] = apx[i - 1], apy[i] = apy[i - 1];
	apx[p] = x, apy[p] = y;
}

void dfs(int now, int lincnt, int acnt)
{
	if (lincnt + acnt >= ans)return;
	if (now > n)
	{
		ans = lincnt + acnt;
		return;
	}
	//a line cross the point
	for (int i = 1; i <= lincnt; i++)
	{
		if (check(i, p[now].x, p[now].y))
		{
			dfs(now + 1, lincnt, acnt);
			return;
		}
	}
	//creat a line
	for (int i = 1; i <= acnt; i++)
	{
		if (cmp(p[now].x, apx[i]) == 0)continue;//这样解出的不是抛物线
		double a = (p[now].y * apx[i] - apy[i] * p[now].x) / (p[now].x * p[now].x * apx[i] - apx[i] * apx[i] * p[now].x);
		if (cmp(a, 0) != -1)continue;//必须是抛物线
		double b = (p[now].y - p[now].x * p[now].x * a) / p[now].x;
		//cout << a << " " << b << endl;
		double tmpx = apx[i], tmpy = apy[i];//记录回溯的值
		lina[lincnt + 1] = a;
		linb[lincnt + 1] = b;
		dele(i, acnt);//删除点
		dfs(now + 1, lincnt + 1, acnt - 1);
		repla(i, acnt, tmpx, tmpy);//回溯这个点
	}
        //以上情况都已尝试,最后尝试将该点孤立去与后面的点构造曲线
	apx[acnt + 1] = p[now].x;
	apy[acnt + 1] = p[now].y;
	dfs(now + 1, lincnt, acnt + 1);
}

int main()
{
	fastio;
	int t;
	cin >> t;
	while (t--)
	{
		cin >> n >> m;
		ans = n;
		for (int i = 1; i <= n; i++)
		{
			double x, y;
			cin >> x >> y;
			p[i] = { x,y };
		}
		dfs(1, 0, 0);
		cout << ans << endl;
	}
	return 0;
}

②acwing 2069. 网络分析

用并查集维护构造树进行树上差分

#include<bits/stdc++.h>
#include<unordered_map>
#define ll long long
#define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
double pi = acos(-1);
const double eps = 1e-6;
const int maxn = 1e5 + 10;
const int inf = 1e9;

ll mod = 998244353;

int edge_cnt = 0, head[maxn];

struct edge {
	int to;
	int next;
}e[maxn << 1];

inline void add(int from, int to)
{
	e[++edge_cnt] = { to,head[from] };
	head[from] = edge_cnt;
}

int fa[maxn];

int anc(int x)
{
	return fa[x] == x ? x : fa[x] = anc(fa[x]);
}

int ans[maxn];
int n, m;

void dfs(int from)
{
	for (int i = head[from]; i != -1; i = e[i].next)
	{
		int to = e[i].to;
		ans[to] += ans[from];
		dfs(to);
	}
}

int main()
{
	//fastio;
	memset(head, -1, sizeof(head));
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= 2 * n; i++)
		fa[i] = i;
	int cnt = n + 1;

	while (m--)
	{
		int o, x, y;
		scanf("%d%d%d", &o, &x, &y);
		if (o == 1)
		{
			x = anc(x), y = anc(y);
			if (x != y)
			{
				fa[x] = fa[y] = cnt;
				add(cnt, x);
				add(cnt, y);
				cnt++;
			}
		}
		else
		{
			ans[anc(x)] += y;
		}
	}



	for (int i = n + 1; i < cnt; i++)
	{
		//cout << i << " " << fa[i] << endl;
		if (fa[i] == i)
			dfs(i);
	}

	for (int i = 1; i <= n; i++)
		printf("%d ", ans[i]);

	return 0;

}

③acwing 2068. 整数拼接

开一个二位dp数组,假设这个数为x,在第二维的x%k这一个位置的第一维上记录x末尾加上i位再模k的值,之后就直接查询之前是否出现过一个数模k能和现在这个数模k相加等于k的倍数即可

#include<bits/stdc++.h>
#include<unordered_map>
#define ll long long
#define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
double pi = acos(-1);

const double eps = 1e-6;
const int maxn = 1e5 + 10;
const int inf = 1e9;

ll mod;

ll dp[20][maxn], a[maxn];

ll ans, n;

ll mi(ll x) 
{	
	ll res = 0;
	while (x)
	{
		x /= 10;
		res++;
	}
	//cout << res << endl;
	return res;
}

void solve()
{
	for (int i = 1; i <= n; i++)
	{
		ans += dp[mi(a[i])][(mod - a[i] % mod) % mod];
		//cout << mi(a[i]) << " " << mod - a[i] % mod <<" "<< dp[mi(a[i])][mod - a[i] % mod] << endl;
		ll tmp = a[i] % mod;
		for (int j = 1; j <= 10; j++)
		{
			tmp = tmp * 10 % mod;
			dp[j][tmp]++;
		}		
	}
}

int main()
{
	fastio;
	cin >> n >> mod;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	ans = 0;
	solve();
	reverse(a + 1, a + n + 1);
	memset(dp, 0, sizeof(dp));
	solve();
	cout << ans;
	return 0;

}
原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/13768523.html