BestCoder Round #81

来源:互联网 发布:ec软件下载 编辑:程序博客网 时间:2024/06/07 11:07

只会做前三道啊,还有很长的路要走啊喂


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 10000009int 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>




0 0