jz集訓 8.20

50

T1 旅遊

Description

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希望旅遊的總時間儘可能長。

Input

第一行輸入兩個整數N, M;

接下來N行每行M個整數,第x行第y個整數代表A[x][y];

接下來N行每行M個整數,第x行第y個整數代表B[x][y];

注意,有一些A[x][y]=B[x][y]=0,說明這個景點已經拆除,不能遊覽;

Output

輸出一行代表最長的總時間。

Sample Input

4 5

1 2 6 0 2

1 3 4 0 4

0 0 4 0 3

2 2 0 0 4

1 3 5 0 2

2 8 1 0 2

0 0 3 0 4

0 5 0 0 3

Sample Output
39

【樣例說明】

遊覽順序爲(2,1)->(1,5)->(2,2)->(4,5)->(1,3)

Data Constraint

對於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

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

Solution

注意到最優情況肯定是從美觀值小的一路選到大的。
首先對點關於美觀值排序。
對於一個點,僅向第一個比它大的美觀值的所有點連邊。
這就是說,我們將點分成了很多層,分層的依據是美觀值,每相鄰的兩層間連邊。
跑一遍最長路即可。

這個算法顯然是錯的,但它能過。

因爲這個算法連的邊數與美觀值的種類密切相關。
例如:當美觀值僅有1和2,有一半的點是1,一半的點是2,那麼連的邊數就是n4n^4級別的。

T2 做夢

Description

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

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

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

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

Input

第一行輸入兩個整數n, m。

Output

輸出可能的散步過程數%1000000007。

Sample Input

輸入1:

4 2

輸入2:

10 6

Sample Output

輸出1:

4

輸出2:

184

Data Constraint

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

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

n和m均爲偶數

Solution

咕咕咕

T3 數數

Description

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

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

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

Input

第一行輸入一個整數T代表數據組數;

接下來T行每行輸入三個整數A,B,N;

Output

輸出T行,每行一個整數代表答案。

Sample Input

2

4 7 1

5 8 2

Sample Output

3

5

Data Constraint

對於30%的數據:

1<=T<=20 , 1<=A<=10000 , 1<=B<=101610^{16}, 1<=N<=10310^3

對於60%的數據:

1<=T<=20 , 1<=A<=10000 , 1<=B<=101610^{16} , 1<=N<=10910^9

對於100%的數據:

1<=T<=20 , 1<=A<=10000 , 1<=B<=101610^{16} , 1<=N<=101210^{12}

Solution

類歐。
Q:類歐是什麼?
A:解決類似 fa,b,c,n=i=0nai+bcf_{a,b,c,n}=\sum\limits_{i=0}^{n} \lfloor\frac{ai+b}{c}\rfloor的問題的算法,複雜度lognlog_n

Q:怎麼將複雜度降到lognlog_n
A:我們注意到,當aca\geq cbcb\geq c時,令a=amod&ThinSpace;&ThinSpace;ca&#x27;=a \mod cb=bmod&ThinSpace;&ThinSpace;cb&#x27;=b\mod c,有:
fa,b,c,n=i=0nai+bc+n×(n+1)2ac+(n+1)bcf_{a,b,c,n}=\sum\limits_{i=0}^{n} \lfloor\frac{a&#x27;i+b&#x27;}{c}\rfloor+\frac{n\times (n+1)}{2}\lfloor \frac{a}{c} \rfloor +(n+1) \lfloor \frac{b}{c} \rfloor
如果不滿足,令m=an+bcm=\lfloor \frac{an+b}{c} \rfloor則有
fa,b,c,n=nm+fc,cb1,a,m1f_{a,b,c,n}=nm+f_{c,c-b-1,a,m-1}
證明如下:
fa,b,c,n=i=0nai+bcf_{a,b,c,n}=\sum\limits_{i=0}^{n} \lfloor\frac{ai+b}{c}\rfloor
fa,b,c,n=i=0nj=1m(jai+bc)f_{a,b,c,n}=\sum_{i=0}^{n} \sum_{j=1}^m(j\leq \lfloor\frac{ai+b}{c}\rfloor)
fa,b,c,n=i=0nj=0m1(j+1ai+bc)f_{a,b,c,n}=\sum_{i=0}^{n} \sum_{j=0}^{m-1}(j+1\leq \lfloor\frac{ai+b}{c}\rfloor)
fa,b,c,n=i=0nj=0m1(jc+cbai)f_{a,b,c,n}=\sum_{i=0}^{n} \sum_{j=0}^{m-1}(jc+c-b\leq ai)
fa,b,c,n=i=0nj=0m1(jc+cb1&lt;ai)f_{a,b,c,n}=\sum_{i=0}^{n} \sum_{j=0}^{m-1}(jc+c-b-1&lt; ai)
fa,b,c,n=i=0nj=0m1(jc+cb1a&lt;i)f_{a,b,c,n}=\sum_{i=0}^{n} \sum_{j=0}^{m-1}(\lfloor \frac{jc+c-b-1}{a}\rfloor&lt; i)
fa,b,c,n=j=0m1(njc+cb1a)f_{a,b,c,n}=\sum_{j=0}^{m-1}(n-\lfloor \frac{jc+c-b-1}{a}\rfloor)
fa,b,c,n=nm+j=0m1jc+cb1af_{a,b,c,n}=nm+\sum_{j=0}^{m-1}\lfloor \frac{jc+c-b-1}{a}\rfloor
fa,b,c,n=nm+fc,cb1,a,m1f_{a,b,c,n}=nm+f_{c,c-b-1,a,m-1}
得證。

當我在學這個算法的時候,我看到別人的證明過程也十分懵逼,其實理解這個式子要加入一點數形結合的思想。
原式表達的是什麼?
在這裏插入圖片描述
在滿足xNx\in N,yNy\in N,x[0,n]x\in[0, n]y(0,ax+bc]y\in(0,\frac{ax+b}{c}]的二元組(x,y)(x, y)的個數。
第一步轉換就是從x=0x=0枚舉到x=mx=m,發現點就加1。
如下圖:
在這裏插入圖片描述

jj11一直掃到mm

剩下的就是代數變換過程了,不多贅述。

回到本題。
在這裏插入圖片描述

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
typedef unsigned long long ull;
const int L = 65;
ull t,a,b,n,ans;
ull k[L];
ull f(ull a,ull b,ull c,ull n){
	ull res=(n+1)*(b/c);
	if(n & 1){
		res+=(n+1)/2*n*(a/c);
	}
	else{
		res+=n/2*(n+1)*(a/c);
	}
	a%=c;
	b%=c;
	ull m=(a*n+b)/c;
	if(m==0){
		return res;
	}
	return res+n*m-f(c, c-b-1, a, m-1);
}
int main(){
	scanf("%llu",&t);
	k[0]=1;
	for(int i=1; i<62; i++){
		k[i]=k[i-1]*2;
	}
	while(t--){
		scanf("%llu%llu%llu",&a,&b,&n);
		ans=0;
		for(int i=0; i<=60; i++){
			if(b & k[i]){
				ans--;
			}
		}
		for(int i=0; i<=60; i++){
			ans+=f(a, b, k[i], n)-f(a, b, k[i+1], n)*2;
		}
		printf("%llu\n",ans);
	}
	return 0;
}

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