只会做前三道啊,还有很长的路要走啊喂
1001 Machine
有一个机器,它有 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; }
有一个 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>