CSP J 2022 第二輪 VP 划水記

June_Failure發表於2024-04-07

\(day0\)

處於廣州三區,CSP 直接停掉。但是聽說後續會有補測,但是無論如何,鉤子應該是沒有了。

晚上最後複習了快速冪,線段樹,樹狀陣列,就去睡覺了。

收到某人的祝福,挺好的(雖然遠在我家隔壁一條街?)。

\(day1\)

中午 \(12\) 點開始考試,定個鬧鐘,到 \(3:30\)。準時結束。

開了第一題。

題意:給出 \(n\)\(k\),求 \(n^k\) 是否大於 \(10^9\) 是則輸出 \(-1\),否則則輸出 \(n^k\)

額,居然考了快速冪!剛剛好複習到,模板記得很清楚,打出來了。(雖然也很簡單),然後開計算器算了一下 \(sqrt(10^9)\),大於他判一下就可以。

用了不到 \(10min\) 輕鬆 \(AC\)

#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
#define ll long long
ll ans=1;
void Slove(ll a,ll b)
{
	ll base=a;
	while(b>0)
	{
		if(b&1)
			ans*=base;
		base*=base;
		b>>=1;
		if(ans>1000000000)
			cout<<"-1"<<endl,exit(0);
	}
}
int main()
{
// 	freopen(".in","r",stdin);
// 	freopen(".out","w",stdout);
	ll a,b;
	cin>>a>>b;
	if(a>31622&&b>2)
		cout<<"-1"<<endl,exit(0);
	Slove(a,b);
	cout<<ans<<endl;
	return 0;
}

很快開了第二題。

題意:

求兩個正整數 \(p\)\(q\),使 \(n=p\times q\)\((p-1)\times (q-1)=e\times d\)。給出 \(n\)\(d\)\(e\),同時有多測。

透過移項,帶入,可以得到:

\[\begin{cases}p\times q=n \\p+q=n+2-e \times d\end{cases} \]

一開始我還想著去列舉因數,但是發現 \(n\) 的值過大,不可做。

正在想期間,我突然回想起我們最近數學學的,完全平方公式。

\((p-q)^2=(p+q)^2-4\times p\times q\)

再連立 \(p+q\)\(p-q\) 即可求出 \(p\)\(q\)

還要考慮當前的數開平方後進行驗證,即這個數是不是完全平方,還有除以 \(2\) 的部分也要判一下。因為在這兩個操作會有精度損失。

最後還要記得要先輸出小的。

#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
#define ll long long
int main()
{
// 	freopen(".in","r",stdin);
// 	freopen(".out","w",stdout);
	int t;
	cin>>t;
	while(t--)
	{
		ll n,e,d;
		cin>>n>>d>>e;
		ll m=n-e*d+2;
		ll s=sqrt(m*m-4*n);
		if(s*s!=m*m-4*n){
			cout<<"NO"<<endl;continue;
		}
		ll p=(m+s)>>1;
		if(p*2!=m+s)
		{
			cout<<"NO"<<endl;continue;
		}
		ll q=n/p;
		if(p>q)
			swap(p,q);
		cout<<p<<" "<<q<<endl;
	 } 
	return 0;
}


考試的時候輸入順序寫錯了,調了 \(10min\) 才發現,我真的會謝。

看到 \(T3\) 題目很長,果斷跳開,選擇性躲避,開了 \(T4\)

\(T4\) 一開始沒認真讀題,理解錯題目以為線只可以平行於 \(x\) 或者 \(y\) 軸,對了樣例看了一會,才發現他是可以斜著走的。。。

給出 \(n\) 個點座標,以及可以新增 \(k\) 個點。從中挑選出一些點,加入一些點,是的點兩兩之間 即 \(x[i+1]-x[i]=1,y[i+1]=y[i]\) 或者 \(y[i+1]-y[i]=1,x[i+1]=x[i]\)

\(30\) 分的做法顯然,就是找個最長不下降子序列且公差為 \(1\) 即可。

正解還是 \(dp\)

\(dp[i][j]\) 表示 第 \(i\) 個點結尾,新增 \(j\) 個點的最大值, \(dis(i,j)\) 表兩點距離(也就是兩個點之間至少還要添幾個點)。

其中 \(l\) 列舉可以新增點的數量。

\[dp[i][l+dis(i,j)-1]=\max(dp[i][l+dis(i,j)-1],dp[j][l]+dis(i,j)) \]

#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
int dp[1000][1000];
struct node
{
	int x,y;
}a[N];
int dis(int i,int j)
{
	return abs(a[i].x-a[j].x+a[i].y-a[j].y);
}
bool cmp(node a,node b)
{
	return a.x==b.x?a.y<b.y:a.x<b.x;
}
int main()
{
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++)
		cin>>a[i].x>>a[i].y;
	for(int i=1;i<=n;i++)
		dp[i][0]=1;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<i;j++)
		{
			if(a[j].y<=a[i].y)
				for(int l=0;(l+dis(i,j)-1)<=k;l++)
					dp[i][l+dis(i,j)-1]=max(dp[i][l+dis(i,j)-1],dp[j][l]+dis(i,j));
		}
	}
	int maxx=-INT_MAX;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=k;j++)
			maxx=max(maxx,dp[i][j]+k-j);
	cout<<maxx<<endl;
 } 

考試的時候在判最大值的之後寫了 \(j=1\) 開始,直接爆掉 \(30\) 分。

笑了,最簡單的最長不下降序列的 \(30\) 分我反而沒拿到。

考完還去問了學長正解,結果差點尷尬了。

\(T4\) 搞了差不多有 \(1h\) \(30min\),留給我的時間不多了。

看回 \(T3\),是一道大模擬。先看特殊性質的分很好搞(主要是沒有優先順序),括號的話透過搜尋判左右區間即可。

雖然剩下還有時間,但是我還是不想搞了。(這一部分搜尋不太熟練。)

最後看到了\(|s|\leq3\) 還有 \(15\) 分鐘,因為不用檢查檔案,我開始了閒情雅緻。開始列舉情況,成功的得到了 \(10\) 分。

賽時程式碼不堪入目,都懂的。

賽後參考了一下題解也打出來了,原來使用棧和 \(vecotr\) 維護。麻了。

結束了。。。等 \(GD\) 自主舉行的考試罷。

成績:\(100+100+60+70=330\)

晚上和 \(npy\) 聊天,瞬間覺悟:還是 \(npy\) 好。

相關文章