2019.08.20【NOIP提高組】模擬 B 組 排序、DP+遞推、矩陣乘法+數位DP/類歐

0 旅遊(travel)

ztxz16如願成爲碼農之後,整天的生活除了寫程序還是寫程序,十分苦逼。終於有一天,他意識到自己的生活太過平淡,於是決定外出旅遊豐富閱歷。

ztxz16生活的城市有NM個景點,可以描述成一個NM的矩形,每個景點有一個座標(x, y) (1 <= x <= N, 1 <= y <= M)以及美觀度A[x][y]和觀賞所需的時間B[x][y],從一個景點(x1, y1)走到另一個景點(x2, y2)需要時間爲它們之間的曼哈頓距離:|x1 - x2| +|y1 - y2|。

爲了防止審美疲勞,ztxz16希望觀賞的景點的的美觀度是嚴格上升的,由於不想太早回家碼代碼,ztxz16希望旅遊的總時間儘可能長。

對於30%的數據:1<=N<=50 , 1<=M<=50

對於60%的數據:1<=N<=300 , 1<=M<=300

對於100%的數據:1<=N<=1000 , 1<=M<=1000

0<=A[x][y]<=1000000

0<=B[x][y]<=10^9

注意:本題輸入數據較大,請注意輸入消耗的時間


因爲矩陣的座標對瀏覽的順序沒有影響而美觀度纔是有影響,所以用美觀度排序,按美觀度的順序隨便dp
(然而這樣可以過似乎是因爲數據水)
(正解好像還要四邊形不等式優化?)


我,差點就可以A過,但是我用了堆排,每次都要刪刪減減那種,就T飛了
然而並不需要堆,因爲沒有插入操作
在這裏插入圖片描述

//#pragma GCC optimize(3)
//#pragma GCC optimize(2)
#include <cstdio>
#include <cstring> 
#include <algorithm>

using namespace std;

const int N=1000006;
int n,m,cnt;
long long ans;
unsigned int a[1003][1003];
long long f[N];
struct cv{
	int w,x,y;
	long long f;
}b[N];

inline int read(){
	char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	int x=0;
	while (ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x;
}

inline int abs(int a){
	return (a>0?a:-a);
}

bool comp(cv a,cv b){
	return a.w<b.w;
}

int main(){
	n=read();m=read();
	for (register int i=1;i<=n;i++){
		for (register int j=1;j<=m;j++){
			a[i][j]=read();
		}
	}
	for (register int i=1;i<=n;i++){
		for (register int j=1;j<=m;j++){
			int c=read();
			if (c==0&&a[i][j]==0) continue;
			b[++cnt].w=a[i][j],
			b[cnt].x=i,b[cnt].y=j,b[cnt].f=c;
		}
	}
	sort(b+1,b+1+cnt,comp);
	int lr=1,ls=0;
	for (int i=1;i<=cnt;){
		int k=b[i].w;
		while (k==b[i].w){
			int kk=b[i].f;
			for (register int j=lr;j<=ls;j++)
			b[i].f=(long long)(b[i].f<b[j].f+abs(b[j].x-b[i].x)+abs(b[j].y-b[i].y)+kk?
					b[j].f+abs(b[j].x-b[i].x)+abs(b[j].y-b[i].y)+kk:b[i].f);
			i++;
		}
		lr=ls+1,ls=i-1;
	}
	for (int i=lr;i<=cnt;i++)
	ans=(ans<b[i].f?b[i].f:ans);
	printf("%lld",ans);
}

1 做夢(dream)

ztxz16旅遊歸來後十分疲倦,很快就進入了夢中。

在夢中ztxz16結婚生子了,他不得不照顧小寶寶。但這實在太無聊了,於是ztxz16會在散步。夢中ztxz16住在一個類似數軸的街上,數軸上的每個整點是一個街區,每個單位時間內ztxz16可以選擇向左走一個街區或者向右走一個街區,但如果他離開家超過m個單位時間小寶寶會有危險,因此ztxz16必須在距離上次在家中不超過m個單位時間內回到家中。

n個單位時間後ztxz16會醒來,他希望此時正好在家中。

ztxz16想知道散步過程可能有多少種不同的散步過程。兩個散步過程被認爲不同,當且僅當存在至少一個單位時刻ztxz16選擇的走向不同。

對於30%的數據:2<=n<=100, 2<=m<=100

對於100%的數據:2<=n<=10^9, 2<=m<=100

n和m均爲偶數


快樂遞推,在線矩乘

來自題解:
用f[i]代表i時刻回到家中的方案有多少種,觀察發現轉移可以寫成矩陣的形式,於是可以矩陣乘法快速冪轉移

設f[i][j] 表示 i 時間,走到 j 格有多少種方案
對於初始的m格,暴力遞推轉移,即
f[i][j]=f[i1][j1]+f[i1][j+1]f[i][j]=f[i-1][j-1]+f[i-1][j+1]

Q:欸這個由j+1的轉移難道不是有後效性?[菜雞瞪眼.jpg]
A:傻瓜每個i去更新i+1不就好了
在這裏插入圖片描述
初始化:
然而對於求出的結果,我們只關心在偶數時間回到原點的方案數
我們就把f[i][0] (i%2=0) 的值放到存答案的數組a[i][j] 裏,要乘2
a[i][i-1]=1 :i時間走到i-1格只有一種方案
a[i][i]=1 :i時間走到i格只有一種方案,就是一直走

然後矩陣自乘快速冪,n/2次方

此人散步m時間回到家中可以視爲,此人散步到m/2格,所以只用求此人n/2時間走到m/2格的方案

#include <cstdio>
#include <cstring>

using namespace std;

const int mod=1000000007;
int n,m;
long long f[105][105],a[105][105];
long long ans[105][105];

void calc(long long b[105][105]){
	long long d[105][105];
	memset(d,0,sizeof d);
	for (int i=1;i<=m/2;i++)
		for (int j=1;j<=m/2;j++)
			for (int k=1;k<=m/2;k++)
			d[i][j]=(d[i][j]+ans[i][k]*b[k][j])%mod;
	memcpy(ans,d,sizeof d);
}

void dfs(int x){
	if (x==0) return;
	if (x%2==0) dfs(x/2); else dfs(x-1);
	if (x%2==0) calc(ans); else calc(a);
}

int main(){
	scanf("%d%d",&n,&m);
	f[1][1]=1;
	for (int i=1;i<=m-1;i++)
		for (int j=1;j<=m/2;j++){
			f[i+1][j+1]=(f[i+1][j+1]+f[i][j])%mod;
			f[i+1][j-1]=(f[i+1][j-1]+f[i][j])%mod;
		}
	for (int i=2;i<=m/2;i++) a[i][i-1]=1;
	for (int i=1;i<=m/2;i++) a[1][i]=(f[i*2][0]*2)%mod;
	for (int i=1;i<=m/2;i++) ans[i][i]=1;
	dfs(n/2);
	printf("%lld",ans[1][1]);
}

2 數數(count)

ztxz16從小立志成爲碼農,因此一直對數的二進制表示很感興趣。今天的數學課上,ztxz16學習了等差數列的相關知識。我們知道,一個等差數列可以用三個數A,B,N表示成如下形式:

B + A, B + 2 * A, B + 3 * A, …, B + N * A

ztxz16想知道對於一個給定的等差數列,把其中每一項用二進制表示後,一共有多少位是1,但他的智商太低無法算出此題,因此尋求你的幫助。

對於30%的數據:

1<=T<=20 , 1<=A<=10000 , 1<=B<=10^16 , 1<=N<=10^3

對於60%的數據:

1<=T<=20 , 1<=A<=10000 , 1<=B<=10^16 , 1<=N<=10^9

對於100%的數據:

1<=T<=20 , 1<=A<=10000 , 1<=B<=10^16 , 1<=N<=10^12


初見時,她說,“我無力自保,無處可去,無人可依。”
多年後,他說,“我教你射箭,你已有力自保;天下爲家,你已有處可去;得他相伴,你已有人可依。”
——“有力自保,有處可去,有人可依,願你一世安樂無憂”

然後女主就和男主在一起了
然後我最愛的男二就死掉了
然後我第二愛的男三就獨守天下了
整本書我明明最不喜歡男主好嗎嗚嗚嗚

嚶嚶嚶,你們明明有機會的,爲什麼不?!!
害得我一想起來就傷心QAQ

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章