luogu

珠心算:给定一列数,其中有几个数是另外两个数之和

 1、一开始想到的就是三重for循环:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1001;
int a[maxn],n;
int main()
{
    cin>>n;
    for(int i = 1;i<=n;i++)
    {
        cin>>a[i];
    }
    int tot = 0;
    for(int k = 1;k<=n;k++)
        for(int i = 1;i<=n-1;i++)
            for(int j = i+1;j<=n;j++)
                if(a[k] == a[i] + a[j] && a[i] != a[j])
                
                    
                        tot++;
                       
                    
    cout<<tot<<endl;
    return 0;
}

满心欢喜,以为一下就用暴力找到了答案正解,于是发现,不能AC

通过比较输出结果:

发现原来存在这样的情况:如果一个数等于其他对数之和,那就有几对就算了几次,而本题是计算有多少个数是另外两个数之和,即只算一次就可以了。于是傻傻的不再理解正解答案中的什么k++,i = j = 1;

直接多用一个数组,如果找到了置为1,后面如果再找到就不增加了。

于是AC代码就呼之欲出了:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1001;
int a[maxn],n;
int f[10001];
int main()
{
    cin>>n;
    for(int i = 1;i<=n;i++)
    {
        cin>>a[i];
        f[a[i]] = 0;
    }
    int tot = 0;
    for(int k = 1;k<=n;k++)
        for(int i = 1;i<=n-1;i++)
            for(int j = i+1;j<=n;j++)
                if(a[k] == a[i] + a[j] && a[i] != a[j])
                    if(!f[a[k]])
                    {
                        tot++;
                        f[a[k]] = 1;
                    }
    cout<<tot<<endl;
    return 0;
}

 ISBN:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctype.h>
using namespace std;
string s;
int main()
{
    cin>>s;
    int len = s.size(),sb,sum = 0,tot = 1;
    for(int i = 0;i<len-1;i++)
    {
        if(isdigit(s[i]))
        {
            sum += (s[i] - '0') * tot;
            tot++;
        }
    }
    sum %= 11;
    char c = (sum == 10 ? 'X' : (sum + '0'));
    if(c == s[len-1])
        cout<<"Right"<<endl;
    else{
        for(int i = 0;i<len-1;i++)
            cout<<s[i];
        cout<<c<<endl;
    }
    return 0;
}

 统计单词数真的是做的让人无语,七拼八凑的终于得了70分

#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctype.h>
using namespace std;
const int maxn = 1e6+10;
char str[11];
string s;
char ans[maxn][11];
int main()
{
    //freopen("P1308_5.in","r",stdin);
    gets(str);
    getline(cin,s);
    int len = s.size(), r = 0, h = 0;
    for(int i = 0;i<len;i++)
        if(isalpha(s[i]))
            s[i] = tolower(s[i]);
    for(int i = 0;i<strlen(str);i++)
        str[i] = tolower(str[i]);
    int location[len];
    memset(location,0,sizeof(location));
    for(int i = 0;i<len;i++)
    {
        if(s[i] != ' '){
            if(h == 0) location[r] = i;
            ans[r][h++] = s[i];
        }
        else{
            ans[r][h] = '';
            r++;
            h = 0;
        }
    }
    int tot = 0;
    int t = 0;int flag1 = 0;
    for(int i = 0;i<=r;i++)
    {
        int flag = 1;
        for(int j = 0;j<strlen(str);j++)
            if(ans[i][j] != str[j])
                flag = 0;
        if(flag && strlen(str) == strlen(ans[i]))
            tot++;
        if(flag && !flag1)
        {
            flag1 = 1;
            t = location[i];

        }
    }
    if(!tot) cout<<-1<<endl;
    else cout<<tot<<" "<<t<<endl;

    return 0;
}

再也无法找到可以改进的地方了,于是看一下题解,发现原来可以这么简单,字符串题目就是这样,很多字符的使用方式不清楚,造成了束手无策的局面。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctype.h>
using namespace std;
string s1,s2;

int main()
{
    freopen("P1308_7.in","r",stdin);
    getline(cin,s1);
    getline(cin,s2);
    for(int i = 0;i<s1.size();i++)
        s1[i] = tolower(s1[i]);
    for(int i = 0;i<s2.size();i++)
        s2[i] = tolower(s2[i]);
    s1 = ' ' + s1 + ' ';
    s2 = ' ' + s2 + ' ';
    if(s2.find(s1) == string::npos)
    {
        cout<<-1<<endl;
    }
    else{
        int a1 = s2.find(s1);
        int a2 = a1, s = 0;
        while(a2 != string::npos)
        {
            s++;
            a2 = s2.find(s1,a2+1);
        }
        cout<<s<<" "<<a1<<endl;
    }
}

find我知道,只是用了发现会覆盖单词出现的,这里巧妙的用了两个字符串都加了空格

P1553 数字反转做得我伤心

 一开始想依次判断整数、小数、百分数、分子分母数,后来发现不行,太累赘了,太SB了,不是一个正经的人应该做得事,一度放弃,后来,就尝试找到每个. / %的位置,这时候尝试用string.find(a1) != string :: npos找到字符的位置。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
string s;
int main()
{
    cin>>s;
    int len = s.size(),loc = 0,flag = 0;
    char a = '.', b = '/', c = '%';
    loc = len;
    if(s.find(a) != string :: npos)
        loc = s.find(a), flag = 1;
    if(s.find(b) != string :: npos)
        loc = s.find(b), flag = 1;
    if(s.find(c) != string :: npos)
        loc = s.find(c), flag = 1;

    int t = loc - 1;
    while(s[t] == '0') t--;
    if(t < 0) cout<<0;
    else{
        for(int i = t;i>=0;i--)
            cout<<s[i];
    }
    if(flag)
    {
        cout<<s[loc];
        if(s[loc+1])
        {
            int t = loc + 1, t1 = len - 1;
            while(s[t] == '0') t++;
            while(s[t1] == '0') t1--;
            if(t > t1) cout<<0;
            else{
                for(int i = t1;i>=t;i--)
                    cout<<s[i];
            }
        }

    }

    return 0;
}

改了两次:一个是如果输入的是0.0的话,那么也要输出0.0,所以整数那里输出不应该加<<endl了。还有就是1234567890/1234567890,分子和分母的0都应该要去掉。

 

 这道题真的是让我搞得不要不要的,

1、一开始在统计每个字符出现的最大次数竟然都错了,

for(int i = 0;i<len;i++)

            a[s[i] - 'A']++;

   maxL = max(maxL, a[s[i] - 'A']);

这里因为没有考虑到还有其他的字符,所以首先数组不应该只开成int a[26];

统计字符最大出现字数要分开进行:

for(int i = 0;i<len;i++)

        if(s[i] >= 'A' && s[i] <= 'Z')

            a[s[i] - 'A']++;

    for(int i = 0;i<26;i++)

        if(a[i] > maxL) maxL = a[i];

2、还有它这里是按每个字母出现的次数来打印输出的,所以外层应该是for(int i = maxL;i>0;i--),内层为:大写字母的26个字母,然后因为每行行末不能有多余的空格或换行,所以要设置首位标记。

接着最大的挑战出来了:就是怎样让每一行最后一个※后不再出现空格,因为原来的代码是:

for(int i = maxL;i>0;i--){

        int flag = 0,

for(int j = 0;j<=25;j++){

            char c;

            if(a[j] < i) c = ' ';

            else c = '*';

            if(!flag) { cout<<c; flag = 1;}

            else cout<<' '<<c;

        }

        cout<<endl;

}

这里就要再设置一个位置:表示最后一个大于等于当前最高位置的字母在哪里,就在这进行换行,而不再输出多余的空格。

 int tt = 0;

for(int k = 25;k>=0;k--)
if(a[k] >=i) {tt = k; break; }

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
string s,s1,s2,s3,s4;
int a[101];
int main()
{
    getline(cin,s1);
    getline(cin,s2);
    getline(cin,s3);
    getline(cin,s4);
    s = s1 + s2 + s3 + s4;
    int len = s.size(),maxL = 0;
    for(int i = 0;i<len;i++)
        if(s[i] >= 'A' && s[i] <= 'Z')
            a[s[i] - 'A']++;
    for(int i = 0;i<26;i++)
        if(a[i] > maxL) maxL = a[i];
    for(int i = maxL;i>0;i--){
        int flag = 0,tt = 0;
        for(int k = 25;k>=0;k--)
        if(a[k] >=i) {tt = k; break; }
        for(int j = 0;j<=25;j++){
            char c;
            if(a[j] < i) c = ' ';
            else c = '*';
            if(!flag) { cout<<c; flag = 1;}
            else cout<<' '<<c;
        }
        cout<<endl;
    }
    int flag1 = 0;
    for(int i = 0;i<26;i++){
        char t = i + 'A';
        if(!flag1) {cout<<t,flag1 = 1;}
        else cout<<' '<<t;
    }
    return 0;
}

 最后出现的两个测试点RE的情况,只要在分别统计每个字母出现的次数那里,再加一层条件区分:if(s[i] >= 'A' && s[i] <= 'Z'),从一分未得到最后的AC是一个艰难的过程,不过喜悦和成就感也是显而易见的。

原文地址:https://www.cnblogs.com/longxue1991/p/12453599.html