欧美1区2区3区激情无套,两个女人互添下身视频在线观看,久久av无码精品人妻系列,久久精品噜噜噜成人,末发育娇小性色xxxx

五一普轉(zhuǎn)提筆記Day-3

五一普轉(zhuǎn)提筆記Day-3

免責聲明:本人并非原創(chuàng)者,如有不對請指出,勿噴。

上午

1.lower_bound 和 upper_bound

lower_bound(首元素地址,尾元素地址的下一個地址,目標數(shù))

找到第一個不小于k的元素的地址

upper_bound(首元素地址,尾元素地址的下一個地址,目標數(shù))

找到第一個大于k的元素的地址

代碼:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
signed main(){
	int n=10;
	int a[15];
	set<int> se;
	for(int i=1;i<=n;i++) a[i]=i*i;
	cout<< *lower_bound(a+1,a+n+1,15)<<"\n";//16
	cout<< *upper_bound(a+1,a+n+1,15)<<"\n";//16
	for(int i=1;i<=n;i++){
		se.insert(i*i);
	}
	auto y = se.lower_bound(15);
	auto z = se.upper_bound(15);
	cout<<*y<<"\n";
	cout<<*z<<"\n";
	return 0;
}


2.dp(動態(tài)規(guī)劃)

dp分類:

①狀態(tài):基礎(chǔ)

②轉(zhuǎn)移方程:狀態(tài)之間的關(guān)系

③初始化:邊界狀態(tài)的計算

④如何定狀態(tài):所有在變化的量定為狀態(tài)

第一類↓求數(shù)列中的某個值

T1

這道題共有8個變量

所以應(yīng)該有8個維度,但是空間有些太大了。我們可以將守門員和隊長設(shè)為是否選定,其它角色根據(jù)題目設(shè)定,復(fù)雜度n^2但是對于最后一問,這樣做就不可以了,因為兩個隊伍其他人一樣,隊長不一樣,也會被認為不同,不符合題目要求。解決方法是把這些人按價值從大到小排序,然后在選人時就不需要隊長這個維度了,直接把第一個人選為隊長,因為他價值最高。第一次寫這么多分析一道題

T2斐波那契數(shù)列

我們可以很好想到這個代碼:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
signed main(){
	int n;
	cin>>n;
	vector<int> f(n);
	f[0]=0;
	f[1]=1;
	for(int i=2;i<=n;i++){
		f[i]=f[i-1]+f[i-2];
	}
	cout<<f[n]<<"\n";
	return 0;
}


時間復(fù)雜度為O(n)但如果n≥10^9,那就超時了,我們就要再想方法。我們可以求到通項公式,其實我也不會:

但是這也用不了,因為首先有√,精度有問題。其次10^9帶進去太大了,也算不了。我們就要用矩陣。

①矩陣加法:大小相同,對應(yīng)位置相加即可。

②矩陣乘法:一個n*m的矩陣乘一個m*k的矩陣乘后會形成一個n*k的矩陣。先取出第一個矩陣的第x行,第二個矩陣的第y列,對應(yīng)好后相乘結(jié)果在相加,此時就可以求出結(jié)果矩陣第x行第y列的值。

代碼:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
struct matrix{
	int n,m,a[1024][1024];
	matrix(){
		n=m=0;
		memset(a,0,sizeof(a));
	}
}x,y,z;
matrix operator*(const matrix &x,const matrix &y){
	matrix z;
	z.n=x.n;
	z.m=y.m;
	for(int i=0;i<z.n;i++){
		for(int k=0;k<x.m;k++){
			for(int j=0;j<z.m;j++)
				z.a[i][j]=z.a[i][j]+x.a[i][k]*y.a[k][j];
		}
	}
	//ijk 0.51秒
  //kji 0.57秒
  //ikj 0.03秒
}
signed main(){
	int n=1024;
	x.n=x.m=n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			x.a[i][j]=rand();
		}
	}
	y.n=y.m=n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			y.a[i][j]=rand();
		}
	}
	x*y;
	//cout<<"hello";
	return 0;
}

由測試可知,循環(huán)順序為i→k→j會更快。其實我也不知道為什么。

原因:

計算機有三種存儲設(shè)備:緩存,內(nèi)存,硬盤。其中硬盤速度最慢,緩存速度最快。當我們訪問一個元素,計算機會先從緩存中找,如果找不到,就會把這一行中所有的元素存進緩存,這就是為什么把j放到最后是最快的。

PS:理論上緩存比內(nèi)存快100倍!

還沒看懂點這里

回歸正題(T2),我們可以想到用快速冪和矩陣乘法:

代碼:

#include<cstdlib>
#include<cstring>
#include<iostream>

using namespace std;

struct matrix
{
	int n,m;
	int a[3][3];
	matrix()
	{
		n=m=0;
		memset(a,0,sizeof(a));	
	} 
}A,B;

matrix operator*(const matrix &x,const matrix &y)
{//O(n^3)
	//matrix z;
	z.n = x.n;z.m = y.m;
	for (int i=1;i<=z.n;i++)
		for (int k=1;k<=x.m;k++)
			for (int j=1;j<=z.m;j++)
				z.a[i][j] = z.a[i][j] + x.a[i][k] * y.a[k][j];
	return z;
}

matrix ksm(matrix a,int b)//計算a^b
{
	if (b==0)
	{
		matrix c;
		c.n=c.m=a.n;
		for (int i=1;i<=c.n;i++)
			c.a[i][i]=1;
		return c;
	}
	matrix c = ksm(a,b/2);//c=a^(b/2)
	c=c*c;
	if (b&1) c=c*a;
	return c;
} 

int main()
{
	A.n=1;A.m=2;
	A.a[1][1]=0;A.a[1][2]=1;
	
	B.n=2;B.m=2;
	B.a[1][1]=0;B.a[1][2]=1;
	B.a[2][1]=1;B.a[2][2]=1;
	
	C = A * ksm(B,n);
	cout << C.a[1][1] << "\n";
	
	return 0;
}







結(jié)論:與前面幾項有關(guān)就要寫幾項

第一類↑求數(shù)列中的某個值

第二類↓求方案數(shù)

方法:先升維再降維

T3

拆完點后用矩陣乘法+快速冪,就做完了,手有點懶沒寫

T4

不難想到一個基礎(chǔ)的思路:把這道題轉(zhuǎn)化為上午的矩陣乘法+快速冪。

但是有1000個點,直接就TLE了(時間復(fù)雜度O(n^3*log(t)))。我們就要更換思路,我們可以通過加括號和拆括號來求解,復(fù)雜度O(k^3*log(t))

第二類↑求方案數(shù)

第三類↓排列dp

排列:一個序列中每個數(shù)出現(xiàn)且只出現(xiàn)1次

特征:問有多少個排列等有關(guān)排列的問題

核心:插入

維度:f[i]已經(jīng)把1到ii到n插入了

T5

基礎(chǔ)思路是暴力,可時間復(fù)雜度為O(!n),太高了。

分析維度:f[i][j]=方案數(shù)表示已經(jīng)插入1~i其中有j個逆序?qū)Φ姆桨笖?shù)

轉(zhuǎn)移方程:i+1不會與前面所有數(shù)形成逆序?qū)?,會與后面所有數(shù)形成逆序?qū)?。所以轉(zhuǎn)移方程為:f[i][j]→f[i+1][j+i-k],如圖:

代碼如下:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=1e3+10;
int f[maxn][maxn];
signed main(){
	
	int n;
	cin>>n;
	f[0][0]=1;
	for(int i=0;i<n;i++){
		for(int j=0;j<=(i*(i-1))>>1;j++){
			for(int k=0;k<=i;k++){
				f[i+1][j+i-k]+=f[i][j];
			}
		}
	}
	cout<<f[n][n];
	return 0;
}


此時時間復(fù)雜度為O(n^4),很明顯需要優(yōu)化。優(yōu)化后代碼如下:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=1e3+10;
int f[maxn][maxn];
signed main(){
	
	int n;
	cin>>n;
	f[0][0]=1;
	for(int i=0;i<n;i++){
		for(int j=0;j<=1;j++){
			for(int k=0;k<=i;k++){
				f[i+1][(j+i-k)%2]+=f[i][j];
			}
		}
	}
	cout<<f[n][n];
	return 0;
}


此時時間復(fù)雜度為O(n^2),還是不盡人意,還需要優(yōu)化。圖如下:

此時時間復(fù)雜度為O(n),代碼如下:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=1e3+10;
int f[maxn][maxn];
signed main(){
	
	int n;
	cin>>n;
	f[0][0]=1;
	for(int i=0;i<n;i++){
		for(int j=0;j<=1;j++){
			f[i+1][(j+i)%2]+=x*f[i][j];
			f[i+1][j]+=y*f[i][j];
		}
	}
	cout<<f[n][n];
	return 0;
}


但是其實還有更簡單的方法,答案其實就是\frac{!n}{2}

T6

分析維度:f[i][j]=方案數(shù)表示到i時有j個數(shù)比前面都大的方案數(shù)。

我們可以這樣想(轉(zhuǎn)移方程在里面):

T7

)

分析維度:f[i][j]=方案數(shù)表示1~i中的最小值為j時的方案數(shù)。

接下來貼一張圖(轉(zhuǎn)移方程在里面):

第三類↑排列dp

第四類↓區(qū)間dp

核心:區(qū)間

維度f[l][r]表示l到r這個區(qū)間

T8P1775

如圖:

T9

轉(zhuǎn)移方程:

T10

轉(zhuǎn)移方程:f[l][r]=min(f[l][k]+f[k][r]+a_l*a_r*a_k)(l<k<r)

另一種做法:

T11求一個字符串有多少個回文子序列(長度≤10^3)

)

T12

曼哈頓距離:|x_1-x_2|+|y_1-y_2|

如果你設(shè)的維度不能完成題目,就加維度,總可以做的,TLE是另一碼事,先保證代碼正確?!婐╆?/h4>

全部評論

相關(guān)推薦

評論
點贊
收藏
分享

創(chuàng)作者周榜

更多
??途W(wǎng)
??推髽I(yè)服務(wù)