【写在前面】 就不写题意了,紫书上面有中文翻译,下面水题我直接给出代码了,一些需要推导的详细写一下!

【3-1】水题,顺序扫描一遍就行了。复杂度O(len)

char s[82];
bool vis[82];
int main()
{
    int T;
    scanf("%d",&T);
    REP(i, T){
        memset(vis, false, sizeof(vis));
        scanf("%s", s);
        int ans = 0;
        int len = strlen(s);
        REP(i, len){
            if(vis[i] || s[i] == 'X') continue;
            int cnt = 0;
            while(s[i] == 'O'){
                vis[i] = true;
                cnt++, i++;
            }
            ans += cnt * (cnt + 1) / 2;
        }
        printf("%d\n", ans);
    }
    return 0;
}

【3-2】同水题,模拟一下即可。复杂度O(len)
map<char, double> mp;
char s[20];
int main()
{
    mp['C'] = 12.01, mp['H'] = 1.008, mp['O'] = 16.00, mp['N'] = 14.01;
    int T;
    scanf("%d", &T);
    REP(j, T)
    {
        scanf("%s", s);
        int len = strlen(s);
        double ans = 0;
        REP(i, len){
            if(isdigit(s[i])) continue;
            if(isdigit(s[i+1])){
                double cnt = s[i+1] - '0';
                int j = i + 2;
                while(isdigit(s[j])){
                    cnt = cnt * 10 + s[j] - '0';
                    j++;
                }
                ans += cnt * mp[s[i]];
            }
            else{
                ans += mp[s[i]];
            }
        }
        printf("%.3f\n", ans );
    }
    return 0;
}

【3-3】把所有的数字放到数组里面,或者边循环边基数都可以。
int a[100010];
int b[10];

int main()
{
    int T, n;
    scanf("%d", &T);
    REP(k, T){
        int cnt = 0;
        scanf("%d", &n);
        memset(b, 0, sizeof(b));
        for(int i = 1; i <= n; i++){
            int j = i;
            while(j){
                a[cnt++] = j % 10;
                j /= 10;
            }
        }
        for(int i = 0; i < cnt; i++){
            b[a[i]]++;
        }
        for(int i = 0; i < 9; i++){
            printf("%d ", b[i]);
        }
        printf("%d\n", b[9]);
    }
    return 0;
}

【3-4】模拟长度并判断,复杂度O(n^2)
char s[82];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s", s);
        int len = strlen(s);
        int ans;
        for(int i = 1; i <= len; i++){
            bool ok = 1;
            string temp = "";
            for(int j = 0; j < i; j++) temp += s[j];
            for(int j = i; j < len; j += i){
                string xx = "";
                for(int k = j; k < i + j; k++){
                    xx += s[k];
                }
                if(xx != temp){
                    ok = 0;
                    break;
                }
            }
            if(ok){
                ans = i;
                break;
            }
        }
        if(T >= 1)
            printf("%d\n\n", ans);
        else{
            printf("%d\n",ans);
        }
    }
    return 0;
}

【3-5】纯模拟,没啥说的!
char maze[5][5];
char ope[1010];
bool judge(int x, int y)
{
    if(x >= 0 && x < 5 && y >= 0 && y < 5) return true;
    else return false;
}

int main()
{
    int ks = 0;
    while(gets(maze[0])){
        if(maze[0][0] == 'Z') break;
        gets(maze[1]);
        gets(maze[2]);
        gets(maze[3]);
        gets(maze[4]);
        for(int i = 0; i < 5; i++){
            if(maze[i][4] == '\0'){
                maze[i][4] = ' ';
            }
        }
        int cnt = 0;
        while(~scanf("%c", &ope[cnt])){
            if(ope[cnt] != '0') cnt++;
            else break;
        }
        ope[cnt++] = '0'; getchar();
        int sx, sy;
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 5; j++){
                if(maze[i][j] == ' '){
                    sx = i, sy = j;
                }
            }
        }
        bool ok = 1;
        int len = strlen(ope);
        REP(i, len){
            if(ope[i] == '0') break;
            if(ope[i] == 'L'){
                if(judge(sx, sy - 1)){
                    maze[sx][sy] = maze[sx][sy-1];
                    maze[sx][sy-1] = ' ';
                    sy--;
                }
                else{
                    ok = 0;
                    break;
                }
            }
            if(ope[i] == 'R'){
                if(judge(sx, sy + 1)){
                    maze[sx][sy] = maze[sx][sy+1];
                    maze[sx][sy+1]=' ';
                    sy++;
                }
                else{
                    ok = 0;
                    break;
                }
            }
            if(ope[i] == 'A'){
                if(judge(sx-1, sy)){
                    maze[sx][sy] = maze[sx-1][sy];
                    maze[sx-1][sy] = ' ';
                    sx--;
                }
                else{
                    ok = 0;
                    break;
                }
            }
            if(ope[i] == 'B'){
                if(judge(sx+1, sy)){
                    maze[sx][sy] = maze[sx+1][sy];
                    maze[sx+1][sy] = ' ';
                    sx++;
                }
                else{
                    ok = 0;
                    break;
                }
            }
        }
        if(ks++) printf("\n");
        printf("Puzzle #%d:\n", ks);
        if(ok == 0){
            printf("This puzzle has no final configuration.\n");
        }
        else{
           for(int i = 0; i < 5; i++){
                for(int j = 0; j < 4; j++){
                    printf("%c ",maze[i][j]);
                }
                printf("%c\n",maze[i][4]);
           }
        }
    }
    return 0;
}

【3-6】纯模拟,不过输出要按照序号排序之后再输出。格式有点坑,pe了很多发。
int n, m;
char maze[12][12];
int id[12][12];
bool check(int x, int y)
{
    if(x >= 0 && x < n && y >= 0 && y < m){
        return true;
    }
    else{
        return false;
    }
}
struct node{
    int pos;
    string s;
    bool operator<(const node &rhs) const{
        return pos < rhs.pos;
    }
    void init(){
        pos = 0;
        s = "";
    }
}ans[110];
int main()
{
    int ks = 1;
    while(scanf("%d", &n), n)
    {
        scanf("%d", &m);
        for(int i = 0; i < n; i++){
            scanf("%s", maze[i]);
        }
        for(int i = 0; i < 110; i++){
            ans[i].init();
        }
        int cntt = 0;
        memset(id, 0, sizeof(id));
        int cnt = 0;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(maze[i][j] == '*') continue;
                if((check(i-1, j) == false || maze[i-1][j] == '*') || (check(i, j-1) == false || maze[i][j-1] == '*')){
                    id[i][j] = ++cnt;
                }
            }
        }
        if(ks>1) printf("\n");
        printf("puzzle #%d:\n", ks++);
        printf("Across\n");
        int k;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j += k){
                if(id[i][j] != 0){
                    //printf("  %d.", id[i][j]);
                    ans[cntt].pos = id[i][j];
                    k = 0;
                    while( maze[i][j+k] != '*' && (j + k) < m){
                        //printf("%c", maze[i][j+k]);
                        ans[cntt].s += maze[i][j+k];
                        k++;
                    }
                    //printf("\n");
                    cntt++;
                }
                else{
                    k = 1;
                }
            }
        }
        sort(ans, ans+cntt);
        for(int i = 0; i < cntt; i++){
            printf("%3d.",ans[i].pos);
            cout<<ans[i].s<<endl;
        }
        cntt = 0;
        for(int i = 0; i < 110; i++){
            ans[i].init();
        }
        printf("Down\n");
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j += k){
                if(id[j][i] != 0){
                    //printf("  %d.", id[j][i]);
                    ans[cntt].pos = id[j][i];
                    k = 0;
                    while(maze[j+k][i] != '*' && (j + k) < n){
                        //printf("%c", maze[j+k][i]);
                        ans[cntt].s += maze[j+k][i];
                        k++;
                    }
                    cntt++;
                    //printf("\n");
                }
                else{
                    k = 1;
                }
            }
        }
        sort(ans, ans+cntt);
        for(int i = 0; i < cntt; i++){
            printf("%3d.",ans[i].pos);
            cout<<ans[i].s<<endl;
        }
    }
    return 0;
}

【3-7】贪心,找每一列出现最多的那个字母!复杂度O(n*m)
char s[1002];
struct node{
    int a, c, g, t;
    void init(){
        a = 0, c = 0, g = 0, t = 0;
    }
}thing[1005];

int main()
{
    int T, n, m;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 0; i < m; i++){
            thing[i].init();
        }
        for(int i = 0; i < n; i++){
            scanf("%s", s);
            for(int j = 0; j < m; j++){
                if(s[j] == 'A') thing[j].a++;
                else if(s[j] == 'C') thing[j].c++;
                else if(s[j] == 'G') thing[j].g++;
                else thing[j].t++;
            }
        }
        char ans[1005] = {'0'};
        int maxx, anss = 0;
        for(int i = 0; i < m; i++){
            ans[i] = 'A';
            maxx = thing[i].a;
            if(thing[i].c > maxx){
                ans[i] = 'C';
                maxx = thing[i].c;
            }
            if(thing[i].g > maxx){
                ans[i] = 'G';
                maxx = thing[i].g;
            }
            if(thing[i].t > maxx)
            {
                ans[i] = 'T';
                maxx = thing[i].t;
            }
            anss += n - maxx;
        }
        ans[m] = '\0';
        printf("%s\n", ans);
        printf("%d\n", anss);
    }
    return 0;
}

【3-8】计算循环节。n除以m的余数只能是0~m-1,根据抽屉原则,当计算m+1次时至少存在一个余数相同, 即为循环节;存储余数和除数,输出即可。复杂度O(m)
int a[3003], b[3003], c[3003];

int main()
{
    int n, m, t;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        t = n;
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(c, 0, sizeof(c));
        int cnt = 0;
        a[cnt++] = n/m;
        n = n % m;
        while(!b[n] && n){
            b[n] = cnt; //记录第一次出现的位置
            c[cnt] = n;
            a[cnt++] = 10*n/m;
            n = 10*n%m;
        }
        printf("%d/%d = %d.", t, m, a[0]);
        for(int i = 1; i < cnt && i <= 50; i++){
            if(n && c[i] == n) printf("(");
            printf("%d", a[i]);
        }
        if(n == 0) printf("(0");
        if(cnt > 50) printf("...");
        printf(")\n");
        printf("   %d = number of digits in repeating cycle\n\n", n == 0 ? 1 : cnt - b[n]);
    }
    return 0;
}

【3-9】满足单调性,O(n扫描一下文本串即可!


char s1[100010], s2[100010];

int main()
{
    while(scanf("%s%s", s1,s2) != EOF)
    {
        int len1 = strlen(s1);
        int len2 = strlen(s2);
        int p = 0;
        if(len1 > len2){
            printf("No\n");
            continue;
        }
        for(int i = 0; i < len2; i++){
            if(s2[i] == s1[p]){
                p++;
            }
        }
        if(p == len1){
            printf("Yes\n");
        }
        else{
            printf("No\n");
        }
    }
    return 0;
}

【3-10】根据长方体的特点去判断即可!

struct Plane{
    int x, y;
    bool operator<(const Plane &rhs) const{
        if(x == rhs.x) return y > rhs.y;
        return x > rhs.x;
    }
}p[6];
bool judge(){
    if(memcmp(p, p + 1, sizeof(Plane)) || memcmp(p + 2, p + 3, sizeof(Plane)) || memcmp(p + 4, p + 5, sizeof(Plane))) return false;
    if(p[0].x != p[2].x || p[0].y != p[4].x || p[2].y != p[4].y) return false;
    return true;
}
int main()
{
    while(scanf("%d%d",&p[0].x,&p[0].y) != EOF)
    {
        if(p[0].x < p[0].y) swap(p[0].x, p[0].y);
        for(int i = 1; i < 6; i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            if(p[i].x < p[i].y){
                swap(p[i].x, p[i].y);
            }
        }
        sort(p, p + 6);
        if(judge()){
            printf("POSSIBLE\n");
        }
        else{
            printf("IMPOSSIBLE\n");
        }
    }
    return 0;
}

【3-11】固定一个不变,移动宁一个,判断合法性,取最小值 复杂度O(max(len1, len2))
char s1[200], s2[200];
int len1, len2;
int solve(char *s1, char *s2, int n)
{
    int sumlen = len1 + len2;
    int minn = min(len1, len2);
    int len = sumlen;
    REP(i, n){
        int ok = 1, lcm = min(n - i, minn);
        REP(j, lcm){
            if(s1[i + j] == '2' && s2[j] == '2'){
                ok = 0;
                break;
            }
        }
        if(ok && len > sumlen - lcm){
            len = sumlen - lcm;
        }
    }
    return len;
}
int main()
{
    while(scanf("%s%s",s1,s2)!=EOF)
    {
        len1 = strlen(s1);
        len2 = strlen(s2);
        int ans = min(solve(s1, s2, len1), solve(s2, s1, len2));
        printf("%d\n", ans);
    }
    return 0;
}

【3-12】
如果每组数都要计算比较找到对应的m和e运算量太大,所以先打表,涉及浮点数表示的一些数学知识。

  假设当前一层M和E的值为m和e,它们的位数分别为i和j。

  首先计算m的值,用二进制表示的话,m的值为0.11…,也就是m = 2^(-1) + 2^(-2) + … + 2^(-1 - i)(i比实际1的个数少1个),也就是m = 1 - 2^(-1 - i)。

  接下来就是计算e的值,不难得出,e = 2^j - 1。

  那么也就有m * 2^e = A * 10^B,似乎可以直接计算了。然而,直接这样算的话是不行的,因为当e太大的话(e最大可以是1073741823,注意这还只是2的指数),等号左边的数就会超出上限,所以要想继续算下去,就得自己去想办法再写出满足要求的类来,这显然太麻烦了。所以,这个时候我们对等式两边同时取对数,这个时候就有 log10(m) + e × log10(2) = log10(A) + B。因为此时m和e的值都是确定的,所以不妨令等式左边为t,也就有t = log10(A) + B。

  这个时候就有问题了,A和B怎么算。

  科学记数法对于A,有1 ≤ A < 10。那么0 < log10(A) < 1。所以t的小数部分就是log10(A),整数部分就是B,即B = ⌊t⌋,A = 10^(t - B)。那么接下来,我们只需要开出两个二维数组来,分别记录对应i和j下A和B的大小,之后从输入里提取出A和B的大小,去二维数组里面查找对应的i和j即可。

编程知识:

  1.如果浮点数赋值给整数,小数部分会被截取。

  2.类似这样5.699141892149156e76的数据串,想把e两端的数据分别赋给两个变量,可以先用string接收整个数据串,将string中的'e'替换为‘ ’,

再将string拷贝到istringstream的一个对象,再从该对象读取到两个变量即可。


double A[20][40];
long B[20][40];
string s;

void init(){
    REP(m, 9){
        REPZ(e, 30){
            double x = 1 - pow(2, -1 - m), y = pow(2, e) - 1;
            double t = log10(x) + y*log10(2);
            B[m][e] = t;
            A[m][e] = pow(10, t - B[m][e]);
        }
    }
}

int main()
{
    init();
    while(cin>>s){
        if(s == "0e0") break;
        for(auto it = s.begin(); it != s.end(); it++){
            if(*it == 'e'){
                *it = ' ';
                break;
            }
        }
        istringstream is(s);
        double a;
        long b;
        bool ok = 0;
        is>>a>>b;
        REP(m, 9){
            REPZ(e, 30){
                if(b == B[m][e] && (fabs(a - A[m][e]) < 1e-5)){
                    cout<<m<<" "<<e<<endl;
                    ok = 1;
                    break;
                }
            }
            if(ok) break;
        }
    }
    return 0;
}