只會做前三道啊,還有很長的路要走啊喂
有一個機器,它有 m(2≤m≤30) 個彩燈和一個按鈕。每按下按鈕時,最右邊的彩燈會發生一次變換。變換爲:
1. 如果當前狀態爲紅色,它將變成綠色;
2.如果當前狀態爲綠色,它將變成藍色;
3.如果當前狀態爲藍色,它將變成紅色,並且它左邊的彩燈(如果存在)也會發生一次變換。
初始狀態下所有的燈都是紅色的。
詢問按下按鈕 n(1≤n<263) 次以後各個彩燈的顏色。
題解
紅、綠、藍分別表示0、1、2,每次操作就相當於+1,原問題就轉化爲求n的三進制
表示的最低的m位,即求 n mod 3m的三進製表示。
複雜度 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
有一個n行m列的矩陣(1≤n≤1000,1≤m≤1000),在這個矩陣上進行q (1≤q≤100,000) 個操作: 1 x y: 交換矩陣M的第x行和第y行(1≤x,y≤n); 2 x y: 交換矩陣M的第x列和第y列(1≤x,y≤m); 3 x y: 對矩陣M的第x行的每一個數加上y(1≤x≤n,1≤y≤10,000); 4 x y: 對矩陣M的第x列的每一個數加上y(1≤x≤m,1≤y≤10,000);
題解
對於交換行、交換列的操作,分別記錄當前狀態下每一行、每一列是原始數組的哪一行、哪一列即可。
對每一行、每一列加一個數的操作,也可以兩個數組分別記錄。注意當交換行、列的同時,也要交換增量數組。
輸出時通過索引找到原矩陣中的值,再加上行、列的增量。
複雜度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≤長度≤1,000,000 的字符串,僅由小寫字母構成。求有多少個子串,包含有至少k(1≤k≤26)個不同的字母?
有一個明顯的性質:如果子串(i,j)包含了至少k個不同的字符,那麼子串(i,k),(j<k<length)也包含了至少k個不同字符。
因此對於每一個左邊界,只要找到最小的滿足條件的右邊界,就能在O(1)時間內統計完所有以這個左邊界開始的符合條件的子串。
尋找這個右邊界,是經典的追趕法(尺取法,雙指針法)問題。維護兩個指針(數組下標),輪流更新左右邊界,同時累加答案即可。複雜度 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>