首页 > 其他分享 >gjoi 2024.9.27

gjoi 2024.9.27

时间:2024-09-28 11:51:02浏览次数:8  
标签:max 27 gcd int 2024.9 up Ans gjoi define

assert(0);

不嘻嘻。


T1 棋局

首先不难列出 dp 方程 \(f[i][j]\) 表示玩了 \(i\) 局 A 赢了 \(j\) 局的方案数(我们这里钦定玩了 \(R_m+R_h\) 局 A 赢了 \(R_m\) 局),转移 \(f[i][j]\times \frac{j}{i}\to f[i+1][j+1],f[i][j]\times\frac{i-j}{i}\to f[i+1][j]\),仔细思考/画图/大眼观察后发现系数是固定的,预处理逆元/阶乘/阶乘逆元之后直接乘就行了,还要乘一个钦定的组合数。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(register int i=l; i<=r; ++i)
#define dn(i,r,l) for(register int i=r; i>=l; --i)

using namespace std;

const int N=4000005, P=147744151;

int t, xx, yy, x, y, Ans, mul[N], inv[N], fac[N];

int C(int n,int m) {
	if(m<0||n<m) return 0;
	return mul[n]*fac[m]%P*fac[n-m]%P;
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	mul[0]=inv[0]=inv[1]=fac[0]=1;
	up(i,1,4000000) mul[i]=mul[i-1]*i%P;
	up(i,2,4000000) inv[i]=inv[P%i]*(P-P/i)%P;
	up(i,1,4000000) fac[i]=fac[i-1]*inv[i]%P;
	cin >> t;
	while(t--) {
		cin >> xx >> yy >> x >> y;
		Ans=C(xx+yy,xx), xx+=x, yy+=y;
		Ans=Ans*fac[xx+yy-1]%P*mul[x+y-1]%P; 
		Ans=Ans*mul[xx-1]%P*fac[x-1]%P;
		Ans=Ans*mul[yy-1]%P*fac[y-1]%P;
		cout << Ans << '\n';
	}
	return 0;
}

T2 庆典

拆成两个问题,到一个点的距离最长是多少,定向到这个点代价是多少,注意到每个点上都有游客所以问题是一个分讨的简单问题,马上做完了。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(register int i=l; i<=r; ++i)
#define dn(i,r,l) for(register int i=r; i>=l; --i)
#define pb push_back

using namespace std;

const int N=200005;

int n, d, f[N], g[N], Ans=1e18;
struct node { int v, w, opt; };
vector<node> to[N]; 

void dfs(int x,int fad) {
	for(node p:to[x]) {
		int y=p.v, w=p.w;
		if(y==fad) continue;
		dfs(y,x);
		f[x]=max(f[x],f[y]+w);
		g[x]+=g[y]+(!p.opt);
	}
}

void solve(int x,int fad,int pre,int val) {
	int sum=0;
	vector<int> L, R;
	L.pb(0), R.pb(0);
	for(node p:to[x]) {
		int y=p.v, w=p.w;
		if(y==fad) continue;
		L.pb(f[y]+w);
		R.pb(f[y]+w);
	}
	L.pb(0), R.pb(0);
	up(i,1,L.size()-1) L[i]=max(L[i-1],L[i]);
	dn(i,R.size()-2,0) R[i]=max(R[i+1],R[i]);
	int cnt=0;
	for(node p:to[x]) {
		int y=p.v, w=p.w;
		if(y==fad) continue;
		++cnt;
		solve(y,x,max(pre,max(L[cnt-1],R[cnt+1]))+w,val+g[x]-g[y]-(!p.opt)+p.opt);
	}
	if(max(f[x],pre)<=d) Ans=min(Ans,n-1-g[x]-val);
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> d;
	up(i,2,n) {
		int u, v, w;
		cin >> u >> v >> w;
		to[u].pb((node){v,w,1});
		to[v].pb((node){u,w,0});
	}
	dfs(1,0), solve(1,0,0,0);
	if(Ans==1e18) Ans=-1;
	cout << Ans;
	return 0;
}

T3 游戏

考虑到固定一个左端点之后往右拓展只会有 \(\log V\) 种本质不同的 \(\gcd\),我们先枚举被删除的最左边的数 \(i\) 那会有一个 \(\gcd(a_l,\dots,a_{i-1})\) 的贡献,这种贡献本质不同的段数显然也是 \(\log\) 的,我们考虑把这一段一起考虑,发现取最右边的最好,因为左边贡献一致的情况下可以尽可能让后面的 \(\gcd\) 更大。按照这个思路进行枚举枚举量最多是 \(\log^3 V\) 的,写 st 表+二分 gcd 可以做到 3 只,但因为常数小 \(O(n\log^4V)\) 可以通过,太牛了。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(register int i=l; i<=r; ++i)
#define dn(i,r,l) for(register int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back

using namespace std;

const int N=400005, M=log2(N)+1;

int n, q, t, a[N], f[N][M], lg[N];
vector<pii> L[N], lyl, lsy;

inline int gcd(int a,int b) {
	if(a==0||b==0) return a|b;
	int az=__builtin_ctz(a), bz=__builtin_ctz(b), z=min(az,bz), dif;
	b>>=bz;
	while(a) {
		a>>=az, dif=b-a;
		az=__builtin_ctz(dif);
		if(a<b) b=a;
		a=dif<0?-dif:dif;
	}
	return b<<z;
}

inline int qur(int l,int r) {
	if(l>r) return 0;
	int k=lg[r-l+1];
	return gcd(f[l][k],f[r-(1<<k)+1][k]);
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> q, t=log2(n);
	up(i,1,n) cin >> a[i], f[i][0]=a[i], lg[i]=log2(i);
	up(j,1,t) up(i,1,n) f[i][j]=gcd(f[i][j-1],f[i+(1<<j-1)][j-1]);
	dn(i,n,1) {
		int lst=0;
		for(pii p:lyl) {
			int x=p.first, d=gcd(p.second,a[i]);
			if(d!=lst) lst=d, lsy.pb(mp(x,d));
		}
		if(i==n||a[i+1]%a[i]) lsy.pb(mp(i,a[i]));
		lyl=lsy, lsy.clear();
		for(pii p:lyl) L[i].pb(mp(p.first+1,p.second));
		L[i].pb(mp(i,0)), reverse(L[i].begin(),L[i].end());
	}
	while(q--) {
		int l, r, k;
		cin >> l >> r >> k;
		k=(r-l+1)-k;
		if(k==0) {
			cout << qur(l,r) << '\n';
		}
		if(k==1) {
			int Ans=qur(l,r-1);
			for(pii p:L[l]) {
				int i=p.first;
				if(i>=r) break;
				Ans=max(Ans,gcd(p.second,qur(i+1,r)));
			}
			cout << Ans << '\n';
		}
		if(k==2) {
			int Ans=qur(l,r-1);
			for(pii p:L[l]) {
				int i=p.first;
				if(i>=r) break;
				Ans=max(Ans,gcd(p.second,qur(i+1,r-1)));
				for(pii q:L[i+1]) {
					int j=q.first;
					if(j>=r) break;
					Ans=max(Ans,gcd(gcd(p.second,q.second),qur(j+1,r)));
				}
			}
			cout << Ans << '\n';
		}
		if(k==3) {
			int Ans=qur(l,r-1);
			for(pii p:L[l]) {
				int i=p.first;
				if(i>=r) break;
				Ans=max(Ans,gcd(p.second,qur(i+1,r-1)));
				for(pii q:L[i+1]) {
					int j=q.first;
					if(j>=r) break;
					Ans=max(Ans,gcd(gcd(p.second,q.second),qur(j+1,r-1)));
					for(pii t:L[j+1]) {
						int k=t.first;
						if(k>=r) break;
						Ans=max(Ans,gcd(gcd(p.second,q.second),gcd(t.second,qur(k+1,r))));
					}
				}
			}
			cout << Ans << '\n';
		}
	}
	return 0;
}

T4 吃豆人

首先先二分一个速度 \(v\) 转化成判定性问题,位置二元组难以维护但是注意到 \(pos_{i-1}\) 一定在里面,所以我们维护合法的另一点即可,容易分讨做到 \(O(n\log n)\) 的判定,但是会超时,注意到一个时刻合法的另一个端点是区间(可以观察后通过分讨做法推得),纯度分讨 \(O(n)\) 判定即可。

#include<bits/stdc++.h>
#define int long long
#define db long double
#define up(i,l,r) for(register int i=l; i<=r; ++i)
#define dn(i,r,l) for(register int i=r; i>=l; --i)

using namespace std;

const int N=100005;
const db eps=1e-10;

int n; db t[N], pos[N];

bool check(db v) {
	db l=0, r=0;
	up(i,0,n-1) {
		db len=(t[i+1]-t[i])*v;
		bool L=l-len<=pos[i+1]&&pos[i+1]<=r+len;
		bool R=pos[i]-len<=pos[i+1]&&pos[i+1]<=pos[i]+len;
		if(L&&R) l=min(l-len,pos[i]-len), r=max(r+len,pos[i]+len);
		else if(R) l-=len, r+=len;
		else if(L) l=pos[i]-len, r=pos[i]+len;
		else return 0;
	}
	return 1;
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n;
	up(i,1,n) cin >> t[i] >> pos[i];
	db l=0, r=1e7;
	while(l+eps<r) {
		db mid=(l+r)/2;
		if(check(mid)) r=mid;
		else l=mid;
	}
	cout << fixed << setprecision(10) << l;
	return 0;
}

标签:max,27,gcd,int,2024.9,up,Ans,gjoi,define
From: https://www.cnblogs.com/chelsyqwq/p/18437197

相关文章

  • 9.27 Speed Test
    9.27CodeforcesRound975(Div.1)Solve:A~D(4/6)Rank:424Rating:\(2164+22=2186\)Pref:2252发挥评价:Normal-这场是速度场,A~Dmin=78max=590不过我直接犯唐,B卡顿,C小调,D更是因为多测不清空,虚空吃两发+30min,痛失33delta。CF2018A简单题,考虑到这个位置,大......
  • java动手动脑-2024.9.28
    枚举类publicclassEnumTest{publicstaticvoidmain(String[]args){Sizes=Size.SMALL;Sizet=Size.LARGE;System.out.println(s==t);System.out.println(s.getClass().isPrimitive());Sizeu=Size.valueOf(&quo......
  • 洛谷P1827 [USACO3.4] 美国血统 题解
    上题目:题目描述农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而不是用图形的方法。你的任务是在被给予奶牛家谱的“树中序遍历”和......
  • 2024.9.28 test
    十三联测#9B给出\(n\)个长度为\(m\)的不同的\(01\)串\(s_i\)。定义长度\(nm\)的好的字符串每\(m\)位都是某个\(s_i\),且\(i\)互不相同。你有打字机,有两种操作,一种是\(p\)的概率打出\(1\),\(1-p\)概率打出\(0\);第二种把\(01\)交换。问最佳操作下,能打出好的......
  • java古明源2024.9.27
    EnumTest.java:packagegu;publicclassEnumTest{publicstaticvoidmain(String[]args){Sizes=Size.SMALL;Sizet=Size.LARGE;//s和t引用同一个对象?System.out.println(s==t);////是原始数据类型吗?System.out.println(s.getClass().isPrimitive());//从字符串中转换Sizeu......
  • 9.27
    importjavax.swing.;importjava.awt.;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.image.BufferedImage;importjava.util.Random;publicclassLoginWithCaptchaextendsJFrame{privateJTextFieldusernameField;......
  • 2024/9/27
    课后作业一importjava.util.Random;classRandomArithmeticProblems{publicstaticvoidmain(String[]args){Randomrandom=newRandom();for(inti=0;i<30;i++){intnum1=random.nextInt(100);intnum2=random.nextInt(100);intoperator=random.......
  • 2024-9-27
    标签标签段落,换行与水平线段落换行水平线实操......
  • 9.27日
    • 枚举类型是一种特殊的类,它不是原始数据类型。• 使用==比较两个枚举变量时,只有当它们指向同一个枚举常量时才返回true。• 枚举类型提供了valueOf方法,可以将字符串转换为对应的枚举常量。• 枚举类型的values()方法可以返回一个包含所有枚举常量的数组,便于遍历所有......
  • 2024/9/27
    publicclassWarehouseInformation{privateStringitemnumber;privateStringitemname;privateStringsuppliername;privateStringwarehousingtime;privateStringshipmenttime;privateStringwarehousenumber;privateStringwarehouseplace;privateintit......