湘潭大学2017年下学期程序设计实践-模拟测试3 题解

XTU 1304 ZUMA!

http://202.197.224.59/exam/index.php/problem/exam_read/id/1304/exam_id/230

思路:暴力乱搞即可。
1.找到2个相邻并且颜色与给你的小球相同的位置,然后我们假设把这个小球放在这里。
2.那么一开始,我们就消掉了2个球。
3.然后我们更新序列,删掉那两个球。判断序列中是否存在3个或以上的球连在一起。
4.若存在,继续删,并且记录下删了多少球。
5.不存在就退出,更新答案。

#include <bits/stdc++.h>
using namespace std;

int ans;
string s;
void doit(int id,char c)
{
    string ss = s;
    int cnt=2;
    string now;
    now = ss.substr(0,id-1);
    now += ss.substr(id+1);
    int flag=1;
    while(flag)
    {
        flag=0;
        for(int i=2;i<now.length();i++)
        {
            if(now[i-2]==now[i]&&now[i-1]==now[i])
            {
                int j=i;
                while(now[j]==now[i]&&j<now.length())
                {
                    j++;
                }
                flag=1;
                cnt+=(j-i+2);
                ss = now.substr(0,i-2);
                ss += now.substr(j);
                break;
            }
        }
        now=ss;
    }

    ans = max(ans,cnt);
}

int main()
{
    int t;
    cin>>t;
    int a[1010];
    while(t--)
    {
        ans=0;
        s.clear();
        int n,c;
        cin>>n>>c;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            s+=(char)(a[i]+47);
        }
        char cc = (char)(c+47);
        for(int i=1;i<s.length();i++)
        {
            if(s[i-1]==s[i]&&s[i]==cc)
            doit(i,cc);
        }
        cout<<ans<<"\n";
    }
    return 0;
}

XTU 1305 斐波那契区间

http://202.197.224.59/exam/index.php/problem/exam_read/id/1305/exam_id/230

思路:暴力枚举。
1.从序列的第三个开始枚举,如果当前值 == 前两个值之和,计数器+1
否则计数器置零。
2.每次都要更新答案。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int t;
    cin>>t;
    int a[10005];
    int n;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);

        int ans=0;
        int cnt=0;
        for(int i=3;i<=n;i++)
        {
            if(a[i]==a[i-1]+a[i-2])
            {
                cnt++;
                ans=max(ans,cnt);
            }
            else
            {
                ans=max(ans,cnt);
                cnt=0;
            }
        }
        cout<<ans+2<<endl;
    }
    return 0;
}

XTU 1306 Love Number

http://202.197.224.59/exam/index.php/problem/exam_read/id/1306/exam_id/230

思路:签到题,只需判断(a-x)%d==0即可。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,d,x;
        scanf("%d%d%d",&a,&d,&x);
        if((a-x)%d==0)
            cout<<"Yes\n";
        else cout<<"No\n";
    }
    return 0;
}

XTU 1307 Beautiful Number

http://202.197.224.59/exam/index.php/problem/exam_read/id/1307/exam_id/230

思路:看起来很难,其实样例已经告诉我们1e18的范围内只有1700多个这样的数字,那么最佳做法就是离线打表啦。
(打表很粗暴,而且离线很麻烦,就不如暴搜,当然推公式也行,前提是会推)
其实我们也可以用暴搜来做,每次搜索到一个符合要求的答案就计数器+1,当然,暴搜不经过剪枝,最坏情况可达到2的63次方,因此我们对每次搜索加入一个“已访问过0”的标志
对于一个已访问过0的数字num,我们只需要搜num<<1|1;
而对于一个没访问过0的数字num,我们需要搜索num<<1和num<<1|1;
并且,在访问num<<1时,它的结尾一定是个0,所以我们需要把访问0标志带上。

下面的代码不是很精简

#include <bits/stdc++.h>
using namespace std;
#define ll long long

int cnta,cntb;
ll a,b;
void dfsa(ll now,int cnt)
{
    if(cnt>1)
        return;
    if(now>=a)
        return;

    if(cnt==1)
        cnta++;

    if(cnt==1)
    {
        dfsa(now<<1|1,cnt);
    }
    else
    {
        dfsa(now<<1,cnt+1);
        dfsa(now<<1|1,cnt);
    }
}

void dfsb(ll now,int cnt)
{
    if(cnt>1)
        return;
    if(now>b)
        return;
    if(cnt==1)
        cntb++;

    if(cnt==1)
    {
        dfsb(now<<1|1,cnt);
    }
    else
    {
        dfsb(now<<1,cnt+1);
        dfsb(now<<1|1,cnt);
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cnta=cntb=0;
        cin>>a>>b;
        dfsa(1,0);
        dfsb(1,0);
        cout<<cntb-cnta<<"\n";
    }
    return 0;
}

XTU 1308 比赛

http://202.197.224.59/exam/index.php/problem/exam_read/id/1308/exam_id/230

思路:
1.我们需要知道对于当前剩余的人数n,要拿出多少人去打比赛,那么暴力算一下就可以了,假设这个人数是base;
2.那么需要增加 base/2 场比赛(两两进行),并且新一轮剩下的人数是:

(n - base) + base/2 = n - base/2

就是:没去比赛的 + 参加比赛并且获胜的 = 目前剩余的

那么每次都这样搞一搞就好了

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n;cin>>n;
        ll ans=0;
        ll cnt=0;
        while(n>1)
        {
            ll base=2;
            while(base<=n)
            {
                base<<=1;
            }
            base>>=1;
            cnt++;
            ans+=base/2;
            n -= base/2;
        }
        cout<<cnt<<" "<<ans<<endl;
    }
    return 0;
}

XTU 1309 唯一的子串

http://202.197.224.59/exam/index.php/exam/problems/exam_id/230

思路:这题就STL乱搞,由于字符串长度较小,是很难超时的。

#include <bits/stdc++.h>
using namespace std;

set<string> st;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        st.clear();
        int m;scanf("%d",&m);
        string s;
        cin>>s;
        for(int i=0;i<s.length()-m+1;i++)
        {
            st.insert(s.substr(i,m));
        }
        for(set<string>::iterator it = st.begin();it!=st.end();it++)
        {
            cout<<*it<<"\n";
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mmingfunnytree/article/details/78851951
今日推荐