代码源第三周

第一题:删删

枚举26个字符,假设这个字符就是这个字符串要删除的字符,然后左右两边分别往中间遍历。当两边不一样时就判断两边有没有哪边是我们当前枚举的字符,如果有就跳过他,操作数++然后继续遍历。如果两边都没有我们当前枚举的字符,说明这个字符不能把字符串变成回文,我们去枚举下一个字符,如果有字符可以把字符串变成回文,那就把操作数记录下来,并保存最小值。最后如果所有字符都不能把字符串变成回文那就输出-1,反之输出最小的操作数。 

代码:

#include <bits/stdc++.h>
//#define ll long long

using namespace std;
typedef long long ll;
const int mod = 1e9+7;

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;

    while (t--)
    {
        char c = '#';
        int n, res = 1e9;
        bool flag = true;
        string str;
        cin >> n >> str;
        for (char i = 'a'; i <= 'z'; i++)
        {
            bool flag = true;
            int l = 0, r = n - 1, ans = 0;
            while (l < r)
            {
                if (str[l] == str[r])l++, r--;
                else
                {
                    if (str[l] == i)l++, ans++;
                    else if (str[r] == i)r--, ans++;
                    else
                    {
                        flag = false;
                        break;
                    }
                }
            }
            if (flag)res = min(res, ans);
        }
        if (res == 1e9)cout << -1 << '\n';
        else cout << res << '\n';
    }
    return 0;
}

第二题:快快变大

用区间dp。先用一个二维数组预处理各个区间的乘积和,然后从长度2开始枚举区间长度(所对应能获得的最大分数)。

状态转移方程:  f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j] + (s[i][k]-s[k+1][j])* (s[i][k] - s[k + 1][j]));

代码:

#include <bits/stdc++.h>
//#define ll long long

using namespace std;
typedef long long ll;
const int mod = 1e6+3;

int n;
ll a[1001];
ll sc=0;

void fun(int m)
{
    sc += (a[m + 1] - a[m]) * (a[m + 1] - a[m]);
    a[m] = (a[m] % mod) * (a[m + 1] % mod);
    if (m != 1) fun(m - 1);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1, less<ll>());
    if (n == 1) cout << 0;
    else
    {
        fun(n - 1);
        cout << sc;
    }
    return 0;
}

第三题:饿饿 饭饭2

这道题乍一看还没看懂。后面才明白题目想表达的是用球上的数字(乘2乘3)得到n个数字。

还是挺好想的:分别将这n个数除以2除以3,等到不能整除的时候看看能不能得到球上的数(也有可能中途就能得到)。这应该是最简的思路了,但是稍微复杂一点也能过。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll>PII;

int gcd(int a, int b)
{
    if (a % b == 0)return b;
    return gcd(b, a % b);
}

bool dfs(int num, int k)
{
    if (num < k)return false;
    bool a = false, b = false;
    if (num % 2 == 0)a = dfs(num / 2, k);
    if (num % 3 == 0)b = dfs(num / 3, k);
    return a || b || num == k;
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        vector<int>v(n);
        for (int i = 0; i < n; i++)cin >> v[i];
        int res = v[0];
        for (int i = 1; i < n; i++)
        {
            res = gcd(v[i], res);
        }
        bool flag = true;
        for (int i = 0; i < n; i++)
        {

            if (v[i] != res && !dfs(v[i], res))
            {
                cout << "NO" << endl;
                flag = false;
                break;
            }
        }
        if (flag)cout << "YES" << endl;
    }
    return 0;
}

第四题:字串分值和

先看下样例解释:

字串f值
a1
ab

2

aba2
abab2
ababc3
  b1
  ba2
  bab2
  babc3
    a1
    ab2
    abc3
      b1
      bc2
        c1

显而易见,暴力枚举肯定能算出来,但也肯定会超时。

不会超时的方法是用乘法原理:每个字母只有在第一次出现时才有贡献度,因此可以统计每个字母在第一次出现的情况下,能被多少子串所包含。往左和往右延伸分别得到个数,二者相乘,就是该字母被不同子串所包含的总次数。

代码:

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

typedef long long LL;

int last[200];

signed main()
{
    string s;
    cin >> s;
    
    int n = s.size();
    s = ' ' + s;
    
    LL ans = 0;
    for (int i = 1; i <= n; i ++)
    {
        ans += (LL)(i - last[s[i]]) * (n - i + 1);
        last[s[i]] = i;
    }
    
    cout << ans << endl;
    return 0;
}

第五题:蒟蒻

这题用map容器自动排序感觉最方便。用两个容器分别记录价格和口感,在经过操作后直接遍历价格计算总和即可。

代码:

#include <bits/stdc++.h>
 
using namespace std;
 
#define int long long
const int mod=1e9+7;
 
map<int,int>mp1;
map<int,int>mp2;
 
void solve()
{
    int op,val,wa;
    cin>>op;
    if(op==1)
    {
        cin>>val>>wa;
        if(mp1.count(val)==0 && mp2.count(wa)==0)
        {
            mp1[val]=wa;
            mp2[wa]=val;
        }
    }
    else if(op==2)
    {
        mp2.erase(mp1.begin()->second);
        mp1.erase(mp1.begin());
    }
    else if(op==3)
    {
        mp1.erase(mp2.begin()->second);
        mp2.erase(mp2.begin());
    }
}
 
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin>>t;
    while(t--)
    {
        solve();
 
 
    }
    int ans=0;
    for(auto x:mp1)
        {
            ans+=x.first;
        }
        cout<<ans<<endl;
    return 0;
}

第六题:锦标赛

这道题的题目理解起来有点难,例如题中“当能力值相差小于获胜参数”中的“另一个玩家被淘汰”便是一个可以省略的干扰因素。完全理解题意以后会发现思路很简单。

很难直接求可能获胜的,但是可以求出必败的人(既差值太大的人)。 总数去除必败的就是可能获胜的。必胜的必定是最大的,所以要从后往前遍历。当出现差值过大的时候直接退出循环(因为再往前肯定是必败的。

代码:

#include <bits/stdc++.h>
 
using namespace std;
 
#define int long long
const int mod=1e9+7;
 
int a[100100];
 
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
 
    sort(a+1,a+1+n);
    int ans=1;
    for(int i=n;i>=2;i--)
    {
        if(a[i]-a[i-1]<=k)
        {
            ans++;
        }
        else
        {
            break;
        }
    }
    cout<<ans<<endl;
    return 0;
}

第七题:可重排列

请按字典序从小到大的顺序输出所有序列,满足序列中有p1个1,p2个2,…,pn个n。

输入格式

第一行一个整数n。第二行n个整数p1,p2,…,pn。

输出格式

按字典序从小到大的顺序一行一行输出所有满足条件的序列,每行一个序列,相邻两个数字需要用空格隔开。

样例输入

3 1 2 2

样例输出

1 2 2 3 3 1 2 3 2 3 1 2 3 3 2 1 3 2 2 3 1 3 2 3 2 1 3 3 2 2 2 1 2 3 3 2 1 3 2 3 2 1 3 3 2 2 2 1 3 3 2 2 3 1 3 2 2 3 3 1 2 3 1 2 3 2 3 1 3 2 2 3 2 1 3 2 3 2 3 1 2 3 3 1 2 2 3 3 2 1 3 1 2 2 3 3 1 2 3 2 3 1 3 2 2 3 2 1 2 3 3 2 1 3 2 3 2 2 1 3 3 2 2 3 1 3 2 3 1 2 3 2 3 2 1 3 3 1 2 2 3 3 2 1 2 3 3 2 2 1

 用dfs枚举每个位置的可能的数字,枚举完最后一位时输出整个数组。

代码:

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

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
int f[N], n, u;
vector<int> v;

void dfs()
{
    if (v.size() == u)
    {
        for (auto i : v)cout << i << " ";
        cout << endl;
        return;
    }
    for (int i = 1; i <= n; i++)
    {
        if (f[i] != 0)
        {
            f[i]--;
            v.push_back(i);
            dfs();
            v.pop_back();
            f[i]++;
        }
    }
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> f[i];
        u += f[i];
    }
    dfs();
    return 0;
}

第八题:进制转换

题面

让我看看是谁不会进制转换,哦原来是我


以不同进制的形式输入n个非负整数,求出它们的和并以m进制的形式输出。使用大写字母 A ~ Z 依次代表10~35, 小写字母 a ~ z 依次代表36~61。

输入格式

第一行输入两个整数

1≤n≤10,2≤m≤62。接下来n行,每行输入一个整数2≤t≤62, 一个t进制数 0≤x≤109。

输出格式

一个m进制数,为最终的结果

输入样例1

2 2 2 1 6 10

输出样例1

111

很基础的题,先把所有读到的t进制数转换成10进制并计算总和,再把总和转换成m进制。

代码:

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

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;

char v[70];

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m;
    vector<ll>mymap(100);
    ll ans = 36;
    for (char c = 'a'; c <= 'z'; c++)
    {
        v[ans] = c;
        mymap[c - 65] = ans++;
    }
    for (char c = '0'; c <= '9'; c++)
        v[c - '0'] = c;
    ans = 10;
    for (char c = 'A'; c <= 'Z'; c++)
    {
        v[ans] = c;
        mymap[c - 65] = ans++;
    }
    ll sum = 0;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        string s;
        int t;
        cin >> t >> s;
        ans = 1;
        int len = s.size();
        for (int j = len - 1; j >= 0; j--)
        {
            if (s[j] >= '0' && s[j] <= '9')sum += (s[j] - '0') * ans;
            else sum += mymap[s[j] - 65] * ans;
            ans *= t;
        }
    }
    string str;
    while (sum)
    {
        ll num = sum % m;
        str += v[num];
        sum /= m;
    }
    reverse(str.begin(), str.end());
    cout << str << endl;
    return 0;
}

 第九题:循环子串

题目描述

一个字符串S是另一字符串T的循环子串当且仅当存在k,T所有字符循环右移k位后得到的新T',满足S是T'的子串。例如: abc 是 cefab的循环子串。 (cefab循环右移2位得到abcef, abc是abcef的子串) 一个串P是完全循环串当且仅当对于它的任一子串H, 都有Hreverse是P的循环子串 (Hreverse为H的倒转, 如abc reverse后 为cba)。给一个长度为n的字符串, 判断它是不是完全循环串。

输入格式

第一行一个正整数t, 表示测试数据组数。对于每一组数据,第一行一个正整数n, 表示字符串的长度。接下来一行一个长度为n的字符串. 仅包含小写字母。

输出格式

对于每组测试数据,如果这个串是完全循环串, 输出YES,否则输出NO。每组测试数据之间输出换行。

数据范围

对于所有数据 有1≤t≤100, 1≤n≤103, ∑n≤103。

样例输入

2 4 ccca 11 eeaafbddfaa

样例输出

YES NO

学了一下string里的substr用法。思路是遇到字符串循环时,也就是需要首尾相连时:直接将输入的字符串变成俩首尾相连即可。用 len=2,开始循环比较字符串。

代码:

#include <bits/stdc++.h>
 
using namespace std;
 
#define int long long
const int mod=1e9+7;
 
const int N=1e3+10;
int a[N];
 
 
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        string s;
        cin>>s;
        s+=s;
 
        bool ok=true;
        for(int len=2;len<=n;len++)
        {
            for(int i=0;i+len<=n;i++)
            {
                string res=s.substr(i,len);
                reverse(res.begin(),res.end());
                if(s.find(res)==s.npos)
                {
                    ok=false;
                }
            }
            if(!ok)break;
        }
        if(ok)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

第十题:饿饿 饭饭之暑假大狂欢

故事接着《饿饿 饭饭 2》,又过了几个月,暑假来啦!!!

这天,cc和他的小伙伴们决定一起去游乐园玩,他们一天将游乐园的所有设施玩了个遍,甚至大摆锤,过山车他们还去了很多次,愉快的时间总是很短暂的,很快时间就来到了晚上,但是你以为一天的娱乐时光就这样结束了吗,那你就猜错啦。

晚上,游乐园晚上的party就开始啦,其中有一个游戏环节,赢的人可以得到免费的西瓜,饿到不行的cc和他的小伙伴非常希望得到这个西瓜。

包括cc和他的小伙伴,有t个玩家参与了这个游戏,每个玩家都有一张带有数字的卡片。第i张卡片上有ni个数字,分别是m1,m2,...mn。

游戏过程中,主持人从袋子里一个一个地取出编号的球。 他用洪亮而清晰的声音大声念出球的编号,然后把球收起来。 如果玩家的卡片上有对应的数字,就可以将它划掉。 最先从他的卡片上划掉所有数字的人获胜。 如果多人同时从他们的卡片上划掉所有数字,那么这些人都不能赢得比赛。 在游戏开始时,袋子里有 100 个球,编号从 1 到 100,所有球的编号都是不同的。

cc偷偷知道了每个玩家的数字。 想请你确定每个玩家是否可以在最有利于他的情况下赢得比赛。

输入格式

第一行给出一个数t,代表t个玩家。接下来第二行到t+1行,每行第一个数为ni,代表这个人手中有n个卡片,接下来给出序列a1...an表示这个人所拥有的卡片的数字。

输出格式

输出t行,每一行给出第i个人在最有利的情况下是否能赢得比赛,可以输出YES, 不可以输出NO。

数据范围

1≤t≤100,1≤n≤100,1≤mi≤100

样例输入

3 1 1 3 2 4 1 2 10 11

样例输出

YES NO YES

 题目的意思就是我们要想在有利的情况下自己胜出,也就是说选出的数都是自己有的,而且自己在第一个清空前不能有别人比自己先清空。那么我们就记录每个玩家的牌的情况,然后判断我们的牌是否完全包含其它玩家的牌,如果有一个完全包含那我们就不能赢。

代码:

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

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
int mymap[101][101];

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t, n;
    cin >> t;
    for (int i = 0; i < t; i++)
    {
        cin >> n;
        for (int j = 0; j < n; j++)
        {
            int num;
            cin >> num;
            mymap[i][num]=1;
        }
    }
    for (int i = 0; i < t; i++)
    {
        bool flag = true;
        for (int j = 0; j < t; j++)
        {
            if (i == j)continue;
            bool st = false;
            for (int k = 0; k <= 100; k++)
            {
                if (mymap[i][k] < mymap[j][k])
                {
                    st = true;
                    break;
                }
            }
            if (!st)
            {
                flag = false;
                break;
            }
        }
        if (!flag)
        {
            cout << "NO" << endl;
        }
        else cout << "YES" << endl;

    }
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无用夜宵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值