BestCoder Round #81

只會做前三道啊,還有很長的路要走啊喂


1001 Machine


有一個機器,它有 m (2\leq m\leq 30)m(2m30) 個彩燈和一個按鈕。每按下按鈕時,最右邊的彩燈會發生一次變換。變換爲:

1. 如果當前狀態爲紅色,它將變成綠色;

2.如果當前狀態爲綠色,它將變成藍色;

3.如果當前狀態爲藍色,它將變成紅色,並且它左邊的彩燈(如果存在)也會發生一次變換。

初始狀態下所有的燈都是紅色的。
詢問按下按鈕 n (1\leq n< {2}^{63})n(1n<263) 次以後各個彩燈的顏色。

題解

紅、綠、藍分別表示0、1、2,每次操作就相當於+1,原問題就轉化爲求nn的三進制

表示的最低的mm位,即求 nn mod 3^m3m的三進製表示。

複雜度 O(m)O(m)

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		long long m,n;
		scanf("%I64d%I64d",&m,&n);
		int a[32];
		memset(a,0,sizeof(a));
		int time = 3;
		for(int i=m-1;i>=0;i--){
			if(n!=0)
				a[i] = n%time;
			n/=3;
		}
		for(int i=0;i<m;i++){
			if(a[i]==0)	printf("R");
			else if(a[i]==1) printf("G");
			else if(a[i]==2)	printf("B");
		}
		printf("\n");
	} 
	return 0;
}

1002  Matrix

有一個nnmm列的矩陣(1 \leq n \leq 1000 ,1 \leq m \leq 1000 )(1n1000,1m1000),在這個矩陣上進行qq  (1 \leq q \leq 100,000)(1q100,000) 個操作:

1 x y: 交換矩陣MM的第xx行和第yy(1 \leq x,y \leq n)(1x,yn);
2 x y: 交換矩陣MM的第xx列和第yy(1 \leq x,y \leq m)(1x,ym);
3 x y: 對矩陣MM的第xx行的每一個數加上y(1 \leq x \leq n,1 \leq y \leq 10,000)y(1xn,1y10,000);
4 x y: 對矩陣MM的第xx列的每一個數加上y(1 \leq x \leq m,1 \leq y \leq 10,000)y(1xm,1y10,000);

題解

對於交換行、交換列的操作,分別記錄當前狀態下每一行、每一列是原始數組的哪一行、哪一列即可。

對每一行、每一列加一個數的操作,也可以兩個數組分別記錄。注意當交換行、列的同時,也要交換增量數組。

輸出時通過索引找到原矩陣中的值,再加上行、列的增量。

複雜度O(q+mn)O(q+mn)



#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
struct node{
	long long v,c;
};
node x[1010],y[1010];
long long a[1010][1010];
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m,p;
		scanf("%d%d%d",&n,&m,&p);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				scanf("%I64d",&a[i][j]);
			}
		}
		for(int i=1;i<=n||i<=m;i++){
			x[i].v = y[i].v = 0;
			x[i].c = y[i].c = i;
		}
		for(int i=0;i<p;i++){
			int q,g,h;
			scanf("%d%d%d",&q,&g,&h);
			if(q==1){
				swap(x[g].c,x[h].c);
			}
			else if(q==2){
				swap(y[g].c,y[h].c);
			}
			else if(q==3){
				x[x[g].c].v += h;
			}
			else if(q==4){
				y[y[g].c].v += h;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				printf("%I64d",a[x[i].c][y[j].c] + x[x[i].c].v + y[y[j].c].v);
				if(j!=m)	printf(" ");
				else printf("\n");
			}
			
		}
	}
	return 0;
}


String


有一個 10\leq10長度\leq 1,000,0001,000,000 的字符串,僅由小寫字母構成。求有多少個子串,包含有至少k(1 \leq k \leq 26)k(1k26)個不同的字母?

有一個明顯的性質:如果子串(i,j)(i,j)包含了至少kk個不同的字符,那麼子串(i,k),(j < k < length)(i,k),(j<k<length)也包含了至少kk個不同字符。

因此對於每一個左邊界,只要找到最小的滿足條件的右邊界,就能在O(1)O(1)時間內統計完所有以這個左邊界開始的符合條件的子串。

尋找這個右邊界,是經典的追趕法(尺取法,雙指針法)問題。維護兩個指針(數組下標),輪流更新左右邊界,同時累加答案即可。複雜度 O(length(S))O(length(S))

<span style="font-size:18px;">#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
#define MAX 10000009
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		char a[MAX];
		int k;
		scanf("%s%d",a,&k);
		int r=-1,ans = 0;
		long long sum = 0 ;
		int n = strlen(a);
		int book[29];		
		memset(book,0,sizeof(book));
		for(int i=0;i<n;i++){
			while(ans<k&&r<n){
				r++;
				if(++book[a[r]-'a']==1)
					ans++;
			}
			if(ans<k)	break;
			sum += (long long)(n - r) ;
			if(--book[a[i]-'a']==0)
				ans--;
		}
		printf("%I64d\n",sum);
	}
	return 0;
}
</span>




發佈了49 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章