1 条题解

  • 0
    @ 2025-8-24 21:53:41

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar StarBird
    StarBird yydStarBird!

    搬运于2025-08-24 21:53:41,当前版本为作者最后更新于2020-06-21 19:48:29,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题解 P3880 【[JLOI2008]提示问题】

    题目传送门

    在博客中食用更佳

    大 膜 你!

    这题,没什么好说的,就是模拟。

    我们考虑,把每一个提示都单独放在一个模块,一个一个处理就好了。


    提示1

    简单的将所有字母换成'.'即可

    题目说简单,貌似也挺简单的,扫一遍字符串,把字母换成'.'就好惹。

    另外,这个模块反正要扫一遍字符串,可以做个辅助,统计一下字母的个数。

    code:

    void hint1()
    {
       sum=0;
       for(int i=0;i<len;++i)//遍历字符串
           if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z') ++sum,printf(".");//如果找到字母,统计字母数并把字母换成.输出
           else printf("%c",str[i]);//如果是普通的符号,就直接输出
       puts("");//别忘了末尾换行
       return;
    }
    

    提示2

    从第1个提示而来,将所有字母的个数求出,再将总个数除以三,得到的最接近商的自然数NN,将第1个提示中的前NN个字母显示

    这里需要把总字母个数除以三再四舍五入,比较麻烦。

    我们已经统计了字母的个数,所以可以手写一个四舍五入 (lz太菜,不会一些奇怪的函数,有会的评论下叭)

    这里可以用(int)number强制转换成intint,会舍弃小数部分,保留整数部分,类似于 [number]\left[number\right],也就是向上取整,则(int)number+1为向下取整。

    四舍五入代码如下:

    int calc(double number)
    {
       if (number==(int)number) return (int)number;//如果两数相等,说明除出来是个整数
       if (number-(int)number<(int)number+1-number) return (int)number;//如果这个数与向下取整的差小于向上取整的差,则应该向下取整
       else return (int)number+1;//否则(这个数与向上取整的差小于向下取整的差),则应该向上取整
       //怎样,是不是很玄学?(huaji
    }
    

    好了,废了那么多笔墨,我们完成了四舍五入。

    接下来,就简单了:把字符串扫一遍,取前 13\frac{1}{3} 的字母改成'.'就好了。也是像 hint1hint1 一样做一些准备工作,我们可以记录 13\frac{1}{3} 的字母在哪个位置。

    code:

    void hint2()
    {
        int mark=calc(1.0*sum/3);//去除四舍五入后的三分之一,注意要*1.0转double
        int total=0;//字母数量
        for(int i=0;i<len;++i)
            if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
            {
                ++total;
                if (total==mark) pos=i;//记录三分之一中最后一个字母的位置
                if (total<=mark) printf("%c",str[i]);//还没到三分之一且是字母,把原字符输出
                else printf(".");//在三分之一线以后的字母,化为'.'输出
            }
            else printf("%c",str[i]);//是普通字符,则直接输出
        puts("");
        return;
    }
    

    提示3

    从第2个提示而来,将剩下的元音字母显示。假如没有可显示的元音字母,则从第1个提示而来,即我们将前2/3的字母显示(同样如不能被3整除则取最接近的整数)

    这个提示分两步:首先要判断有没有可显示的元音字母,如果没有,就要扫一遍整个字符串,取前23\frac{2}{3}的字母输出。

    由于hint2hint2calc函数的帮助,实现起来应该也比较容易,就是判断元音字母的if有点长,菜鸡lz甚至单独写了函数……

    判断元音字母的函数,应该比较好写(唱跳rap篮球+C+V就好惹):

    bool check(char ch)
    {
        if (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u' || ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U') return 1;//没啥好说的,判断就完事了
        return 0;
    }
    

    扫一遍,也没什么难度,写完,这题就差不多了。

    void hint3()
    {
        bool flag=0;//是否有元音字母
        for(int i=pos+1;i<len;++i)//从上次的三分之一线后开始扫
            if (check(str[i])) {flag=1;break;}//扫到了元音字母就记录
        if (flag)//元音字母
        {
            for(int i=0;i<=pos;++i) printf("%c",str[i]);//先把三分之一线以前的字符输出
            for(int i=pos+1;i<len;++i)//找三分之一线之后的元音字母
                if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')//字母
                {
                    if (check(str[i])) printf("%c",str[i]);//元音字母正常输出
                    else printf(".");//辅音字母换成.输出
                }
                else printf("%c",str[i]);//普通字符直接输出
        }
        else//没有可输出的元音字母
        {
            int mx=calc(2.0*sum/3);//找到三分之二线
            int total=0;
            for(int i=0;i<len;++i)
            for(int i=0;i<len;++i)
    	        if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
    	        {
    	            ++total;//统计字母的个数
    	            if (total<=mx) printf("%c",str[i]);//小于三分之二线直接输出
    	            else printf(".");
    	        }
    	        else printf("%c",str[i]);//超过了三分之二线则化成'.'输出
        }
        puts("");
        return;
    }
    

    完成!


    完整程序:

    #include<bits/stdc++.h>
    #define MAXN 60
    using namespace std;
    char str[MAXN];//字符串
    int len,sum,pos;
    int calc(double number)
    {
        if (number==(int)number) return (int)number;
        if (number-(int)number<(int)number+1-number) return (int)number;
        else return (int)number+1;
    }
    bool check(char ch)
    {
        if (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u' || ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U') return 1;
        return 0;
    }
    void hint1()
    {
        sum=0;
        for(int i=0;i<len;++i)
            if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z') ++sum,printf(".");
            else printf("%c",str[i]);
        puts("");
        return;
    }
    void hint2()
    {
        int mark=calc(1.0*sum/3);
        int total=0;
        for(int i=0;i<len;++i)
            if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
            {
                ++total;
                if (total==mark) pos=i;
                if (total<=mark) printf("%c",str[i]);
                else printf(".");
            }
            else printf("%c",str[i]);
        puts("");
        return;
    }
    void hint3()
    {
        bool flag=0;
        for(int i=pos+1;i<len;++i)
            if (check(str[i])) {flag=1;break;}
        if (flag)
        {
            for(int i=0;i<=pos;++i) printf("%c",str[i]);
            for(int i=pos+1;i<len;++i)
                if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
                {
                    if (check(str[i])) printf("%c",str[i]);
                    else printf(".");
                }
                else printf("%c",str[i]);
        }
        else
        {
            int mx=calc(2.0*sum/3);
            int total=0;
            for(int i=0;i<len;++i)
    	        if (str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
    	        {
    	            ++total;
    	            if (total<=mx) printf("%c",str[i]);
    	            else printf(".");
    	        }
    	        else printf("%c",str[i]);
        }
        puts("");
        return;
    }
    int main()
    {
        cin.getline(str,MAXN);//有空格不能用cin或scanf,要用getline或gets
        len=strlen(str);//字符串长度
        hint1();
        hint2();
        hint3();
        return 0;
    }
    

    总结一下本题坑点:

    1.输入有空格,cin和scanf很难用,最好用能读一行的来输入

    2.四舍五入很麻烦

    3.有元音字母不需要输出23\frac{2}{3}的字母

    4.元音字母的判断

    • 1

    信息

    ID
    2837
    时间
    1000ms
    内存
    125MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者