scau2017年初出茅庐题解

18257 一起来填数吧

题意:水题,没什么好说的,就按照题意输出,注意一下输出格式,不要输出行末空格就行

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 55 + 5;
int a[N][N];
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
    int T; cin >> T;
    while(T--)
    {
        int n,m; cin >> n >> m;
        int number = 0;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i & 1)
                    a[j][i] = ++number;
                else
                    a[n-j+1][i] = ++number;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cout << a[i][j];
                if(j != m)
                    cout << " ";
            }
            cout << endl;
        }
        cout << endl;
    }
    return 0;
}

18255 体育课

题意:问一个数组能否在去掉之多一个数诸侯使得数组有序。

有序可以分为递增跟递减两种,其实都一样,你只要判断一种,比如你判断递增,然后倒置一些数组再判断一次(其实就是判断原数组的递减情况),关于如何判断:

以递增为例,可以用一个pre[i]表示数组中以第i个数结尾的连续递增个数,用suff[i]表示以第i个数为开头的递增个数,这两个都这样扫一遍数组就可以得到。然后判断的时候根据a[i-1],a[i+1]的值,以及pre[i-1],suff[i+1]的值,就可以很快判断出移除第i个数能否使得原数组有序。时间复杂度O(n),每次记得清空pre以及suff数组。

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 1000 + 5;
const int INF = 10000;
int pre[N],suff[N];
int a[N],n;
bool check(int cond)
{
    memset(pre,0,sizeof(pre));
    memset(suff,0,sizeof(suff));
    if(cond)
        for(int i=1;i<=n/2;i++)
            swap(a[i],a[n-i+1]);

    for(int i=1; i<=n; i++)
    {
        if(a[i] >= a[i-1])
            pre[i] = pre[i-1] + 1;
        else
            pre[i] = 1;
    }

    for(int i=n;i>=1;i--)
    {
        if(a[i] <= a[i+1])
            suff[i] = suff[i+1] + 1;
        else
            suff[i] = 1;
    }

    for(int i=1;i<=n;i++)
    {
        if(a[i+1] >= a[i-1] && pre[i-1] + suff[i+1] == n-1)
            return true;
    }
    return false;
}
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i=1; i<=n; i++)
            cin >> a[i];
        a[n+1] = INF;

        if(check(0) || check(1))
            cout << "YES\n";
        else
            cout << "NO\n";
    }
    return 0;
}

18252 Sheep回文串

题意:给你一个字符串,问你最少替换掉多少个字符才能使得原字符串的所有长度为奇数的字串(区分好字串和子序列,字串是要连续的,子序列不需要连续) 为回文串。

看标题显然是某羊出的题。。。应该算思维题吧,分析一下,为了让字符串所有奇数长度的字串都是回文串,其实很容易可以想到最终的字符串肯定是ababababa这种排列的字符串才可以满足要求(当然,aaaaaa)这种当然也是可以的。

知道最终要转换的字符串形式,显然只要对原字符串分奇偶位处理就行了,保留奇数位以及偶数位中出现最多的字符(字母),其他同奇偶的字符去转换,才能得到最小的转换次数。。。。。emmmmm不知道说明白了没有。

还有就是字符串长度较长,最好不要使用string跟cin,亲测cin 667ms,用char 字符串跟scanf 61ms.

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 1000001 + 5;
const int INF = 10000;
int odd[30],even[30];
char s[N];
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
    scanf("%s",s);
    int len = strlen(s);
    for(int i=0;i<len;i++)
        if(i & 1) odd[s[i]-'a']++;
        else even[s[i]-'a']++;
    int oddMax = 0,evenMax = 0;
    for(int i=0;i<26;i++)
        oddMax = max(oddMax,odd[i]),
        evenMax = max(evenMax,even[i]);
    cout << len - oddMax - evenMax << endl;

    return 0;
}

18242 请问您今天要来点魔法吗??

题意:给你一个从n->m的转换,对n每次抹除最后一位之后求和(其实就是 /10 ),然后反过来给你一个m,让你求n。

题目有个误导你的地方,说如果有多个n满足输出最小的。。。。从/10那个地方就可以明显看出,从n->m的这个装换函数显然是单调的。

而且看到数据范围为1e9,这个范围又是单调,那基本就可以肯定就是二分了0.0。

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 1000001 + 5;
int calc(int x)
{
    int sum = 0;
    while(x)
    {
        sum += x;
        x /= 10;
    }
    return sum;
}
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
    int T;
    cin >> T;
    while(T--)
    {
        int m;
        cin >> m;
        int L = 0,R = 1e9;
        while(L < R)
        {
            if(L + 1 == R)
                break;
            int mid = (L + R)/2;
            if(calc(mid) > m)
                R = mid;
            else
                L = mid;
        }
        if(calc(L) == m)
            cout << L << endl;
        else
            cout << -1 << endl;
    }
    return 0;
}

18240 ACMer不得不知道的事儿(四)

题意:给一些变量定义语句以及赋值语句,让你求出最后又多少个变量定义后没有初始值,并输出以及有初始值的变量的值。

显然是模拟题,有两个点需要注意,第一个点是,假设某一个变量前面给了初始值,但是后面再赋值的时候又将一个不知道值的变量赋值给他的话,这个变量就会从确定值又变成不确定值(这个从样例其实也已经可以看出了,b再赋值之后,又将没有初值的a赋给b,所以b到最后的值也是不确定的)。第二个点是:其实题目也有用红色字体标出,常量的值是int类型,所谓的int类型,当然是包括负数的啦,所以要对符号进行处理一下就可以啦。

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 80 + 5;
int nums[30],vis[30];
char s[N];
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
    int n; cin >> n;
    getchar();
    for(int T=1;T<=n;T++)
    {
        string s;
        getline(cin,s);
        int len = s.length();
        if(s.find("int") < len)
        {
            for(int i=s.find("int")+3;i<len;i++)
            {
                if(s[i] >= 'a' && s[i] <= 'z')
                    vis[s[i] - 'a' + 1] = 1;
            }
        }
        else if(s.find("=") < len)
        {
            int pos = s.find("=");
            int x = 0,y = 0;
            for(int i=0;i<pos;i++)
                if(s[i] >= 'a' && s[i] <= 'z')
                    x = s[i] - 'a' + 1;

            for(int i=pos+1;i<len;i++)
                if(s[i] >= 'a' && s[i] <= 'z')
                    y = s[i] - 'a' + 1;

            if(y == 0)
            {
                int sum = 0;
                for(int i = pos + 1;i < len;i++)
                    if(s[i] >= '0' && s[i] <= '9')
                    sum = sum * 10 + s[i] - '0';
                vis[x] = 2;
                if(s.find("-") < len)
                    sum *= -1;
                nums[x] = sum;
            }
            else
            {
                if(vis[y] == 2)
                {
                    vis[x] = 2;
                    nums[x] = nums[y];
                    if(s.find("-") < len)
                        nums[x] = -nums[x];
                }
                else if(vis[y] == 1)
                    vis[x] = 1;
            }
        }
    }
    int res = 0;
    for(int i=1;i<=26;i++)
        if(vis[i] == 1) res++;
    cout << res << endl;
    for(int i=1;i<=26;i++)
        if(vis[i] == 2)
            printf("%c=%d\n",'a'+i-1,nums[i]);

    return 0;
}

18250 寻找SCAU

题意:求字符串中有多少SCAU子序列(注意这次是子序列而不是字串了)。

动态规划的题目,维护一个状态dp[i],表示以当前字符结尾的(子字符串的个数,有S,SC,SCA,SCAU四种情况),然后对于每一个种情况的递归为:    dp[i] = (1...i-1)中所有前一种字符的总和(即如果当前是C就求和1-i-1中所有以S结尾的dp[j],)为了不每次都去求和,可以在每次计算的时候记录一下前面4种情况的总和就完事了。

TAT不大会解释,看代码理解吧。。。

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 100000 + 5;
const int mod = 1e9+7;
ll dp[N];
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
    string s; cin >> s;
    int len = s.length();
    ll cntS,cntC,cntA,cntU;
    cntS = cntC = cntA = cntU = 0;
    for(int i=0;i<len;i++)
    {
        if(s[i] == 'S')
        {
            dp[i] = 1;
            cntS = (cntS + dp[i]) % mod;
        }
        else if(s[i] == 'C')
        {
            dp[i] = cntS;
            cntC = (cntC + dp[i]) % mod;
        }
        else if(s[i] == 'A')
        {
            dp[i] = cntC;
            cntA = (cntA + dp[i]) % mod;
        }
        else
        {
            dp[i] = cntA;
            cntU = (cntU + dp[i]) % mod;
        }
    }
    cout << cntU << endl;
    return 0;
}

 

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值