2022年多校冲刺NOIP联训测试12 && 51nod 2023省选联训 第二场

发现我只是换了个网站做题,还变成ioi赛制。。。。。

A 开根

直接用pow

考场脑抽,打了个二分

code
#include<cstdio>
#include<cmath>
using namespace std;
double n, m;
int main(){
	scanf("%lf%lf",&n,&m);
	printf("%.3lf\n",pow(n, 1 / m));
	return 0;
}

B 迭代

发现

f(aibi)=ai2+bi22aibi=ai+1bi+1

那么

ai+1+bi+1=(ai+bi)2

an+bn=(x+1)2n1

ai+1bi+1=(aibi)2

anbn=(x1)2n1

计算即可

code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

ll qpow(ll x, ll y, ll mod){
	ll ans = 1;
	for(; y; y >>= 1, x = x * x % mod)if(y & 1)ans = ans * x % mod;
	return ans;
}
ll x, n;
const ll mod = 1000000007;
const ll inv2 = 500000004;
ll work(){
	ll p2 = qpow(2, n - 1, mod - 1);
	ll sum = qpow(x + 1, p2, mod);
	ll det = qpow(x - 1, p2, mod);
	ll a = (sum + det) * inv2 % mod;
	ll b = (sum - det + mod) % mod * inv2 % mod;
	ll ans =  a * qpow(b, mod - 2, mod) % mod;
	return ans;
}
int main(){
	int t; scanf("%d",&t);
	for(int i = 1; i <= t; ++i){
		scanf("%lld%lld",&x,&n);
		printf("%lld\n",work());
	}
	return 0;
}

C 平衡树

换根DP,考场一直在乱搞t4结果没有时间打这个题

还有考试时候真的降智啊,什么东西能够快速维护一堆数据的最大值并且支持快速单点修改?线段树啊啊啊啊!!!!

最近对STL有点魔怔了。。。。

维护size,以及该点的s/s,根节点的α就是全局最大值,然后换根DP找最大值次大值,对该点单点修改即可

记得在线啊

code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read(){
	int x = 0;char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
const int maxn = 150005;
struct edge{int to,net;}e[maxn << 1 | 1];
int head[maxn],tot;
void add(int u, int v){
	e[++tot].net = head[u];
	head[u] = tot;
	e[tot].to = v;
}
struct tree{
	long double t[maxn << 2 | 1];
	void modify(int x, int l, int r, int pos, long double val){
		if(l == r){t[x] = val;return;}
		int mid = (l + r) >> 1;
		if(pos <= mid)modify(x << 1, l, mid, pos, val);
		else modify(x << 1 | 1, mid + 1, r, pos, val);
		t[x] = max(t[x << 1], t[x << 1 | 1]);
	}
	long double query(){return t[1];}
}t;
int size[maxn], si, n, k;
long double ap[maxn];
void dfs1(int x,int fa){
	size[x] = 1;
	int mx = 0;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to;
		if(v == fa)continue;
		dfs1(v, x);
		size[x] += size[v];
		mx = max(mx, size[v]);
	}
	t.modify(1, 1, n, x, mx == size[x] - 1 ? 0 : (long double)mx / size[x]);
}
int mx[maxn], cmx[maxn], son[maxn];
void dfs2(int x, int fa){
	int cnt = 0;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to; ++cnt;
		if(size[v] > mx[x]){
			cmx[x] = max(mx[x], cmx[x]);
			mx[x] = size[v]; son[x] = v;
		}else cmx[x] = max(cmx[x], size[v]);
	}
	t.modify(1, 1, n, x, cnt > 1 ? (long double)mx[x] / si : 0);
	ap[x] = t.query();  --cnt;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to; 
		if(v == fa)continue;
		size[x] = si - size[v];
		t.modify(1, 1, n, x, cnt > 1 ? (son[x] == v ? (long double) cmx[x] / size[x] : (long double) mx[x] / size[x]) : 0);
		dfs2(v, x);
	}
	size[x] = si - size[fa];
	t.modify(1, 1, n, x, cnt > 1 ? (son[x] == fa ? (long double) cmx[x] / size[x] : (long double) mx[x] / size[x]) : 0);
}
int main(){
	n = read(), k = read();
	for(int i = 1; i < n; ++i){
		int u, v; u = read(); v = read();
		add(u, v); add(v, u);
	}
	dfs1(1, 0); si = size[1];
	dfs2(1, 0); sort(ap + 1, ap + n + 1);
	int m = read(), las = 0;
	for(int i = 1; i <= m; ++i){
		int a = read() xor (las * k), b = read() xor (las * k);
		printf("%ld\n",las = upper_bound(ap + 1, ap + n + 1, (long double)a / b) - ap - 1);
	}
	return 0;
}

D 致富之路

关于shuffle他活了

首先设day,val分别表示天和价格

对于工厂dayi<=dayj&&vali<=valj那么要j没有用

对于商店dayi<=dayj&&vali<=valj那么要i没有用

用栈去除无用信息

如果一个商店在他结束之前没有工厂的val小于他,那么该商店没有贡献,扔掉

这样剩下的商店一定存在决策点

然后我们证明存在决策单调性

x工厂劣于y工厂(x<y

那么(dayxday)(valxval)<(dayyday)(valyval)

dayxvalx+day(valyvalx)<dayyvaly+val(dayxdayy)

因为我们按照天数排序并维护单调递减的价格

发现day(valyvalx)val(dayxdayy)小于0

day单调递增,左边越来越小,val单调递减右边越来越大,所以当前x不优,以后一定不优

分治solve(l1,r1,l2,r2)每次给mid商店找决策点,两边递归即可

code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<random>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read(){
	int x = 0;char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
const int maxn = 500055;
int n, m;
struct node{
	int val,day;
	bool operator < (const node &x)const{
		return x.day > day;
	} 
}a[maxn],b[maxn],ls[maxn];
int sta[maxn], stb[maxn], ta, tb;
ll ans = 0;

void solve(int l1, int r1, int l2, int r2){
	if(l1 > r1 || l2 > r2)return;
	int mid = (l2 + r2) >> 1;
	int pos = 0;
	ll mx = -0x3f3f3f3f;
	for(int i = l1; i <= r1; ++i){
		ll nans = (0ll + b[mid].day - a[i].day) * (0ll + b[mid].val - a[i].val);
		if(nans > mx){mx = nans, pos = i;}
	}
	ans = max(ans, mx);
	solve(l1, pos, l2, mid - 1);
	solve(pos, r1, mid + 1, r2);
}
int main(){
	m = read(), n = read();
	for(register int i = 1; i <= m; ++i)a[i].val = read(), a[i].day = read();
	for(register int i = 1; i <= n; ++i)b[i].val = read(), b[i].day = read();
	sort(a + 1, a + m + 1); sort(b + 1, b + n + 1);
	for(register int i = m; i >= 1; --i){
		while(ta && a[sta[ta]].val >= a[i].val)--ta;
		sta[++ta] = i;
	}
	for(int i = 1; i <= ta; ++i)ls[i] = a[sta[ta - i + 1]];
	for(int i = 1; i <= ta; ++i)a[i] = ls[i];
	for(register int i = 1; i <= n; ++i){
		while(tb && b[stb[tb]].val <= b[i].val)--tb;
		stb[++tb] = i;
	}
	for(int i = 1; i <= tb; ++i)ls[i] = b[stb[i]];
	for(int i = 1; i <= tb; ++i)b[i] = ls[i];
	int mi = 0x3f3f3f3f, pa = 1, pb = 0;
	for(int i = 1; i <= tb; ++i){
		while(pa <= ta && a[pa].day < b[i].day)mi = min(mi, a[pa++].val);
		if(mi < b[i].val)ls[++pb] = b[i];
	}
	tb = pb;
	for(int i = 1; i <= tb; ++i)b[i] = ls[i];
	solve(1, ta, 1, tb);
	printf("%lld\n",ans);
	return 0;
}
posted @   Chen_jr  阅读(88)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示