1. 程式人生 > 實用技巧 >「考試總結2020-08-03」可期

「考試總結2020-08-03」可期

T1 斐波那契

題意去 \(luogu\) 上面看吧

通過觀察發現每個月的增量構成了斐波那契數列

然後我們字首和,還照樣是個斐波那契數列(這個好像我原來還不知道)

所以可以發現每個點的父親標號為

\[x-fib[id_x-1] \]

其中 \(fib_{idx}\) 為大於等於 \(x\) 的首個斐波那契數

我的做法是暴力記錄一個點到根路徑上的所有值

然後掛成了 \(70\)\(luogu\) 上就可以過了)

然後學習發現可以對於兩個點每次跳那個標號大的點的父親,然後手寫個二分就能過去了

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar();
		return res*f;
	}
	const int N=100,inf=1e12;
	int fib[N],x=4,s[N]; set<int> st;
	inline int calc(int val)
	{
		int l=1,r=x,ans=x;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			
			if(s[mid]>=val) ans=mid,r=mid-1;
			else l=mid+1;
		}
		return ans;
	}
	inline void work()
	{
		st.clear();
		int a=read(),b=read();
		while(a!=b)
		{
		    if(a<b) swap(a,b);
		    int ma=calc(a); a-=s[ma-1];
		}
		printf("%lld\n",a);
		return ;
	}
	signed main()
	{
		fib[1]=s[1]=1; s[2]=(fib[2]=1)+1; s[3]=(fib[3]=1)+2;
		while(s[x-1]<=inf) fib[x]=fib[x-1]+fib[x-2],s[x]=s[x-1]+fib[x],++x; --x;
		int T=read(); while(T--) work();
		return 0;
	}
}
signed main(){return yspm::main();}

T2 數顏色

題面去 \(Luogu\)

本題卡主席樹,然後換了個 \(vector\)

就過去了

T3 矩陣遊戲

推式子,暴力 \(80\) 都挺無腦的

但是正解好像比 \(80\) 還好寫……

就是個推式子

固定一維推一維

沒想著寫 \(\sum\) 毀了我

T4 優美的序列

link