Week16

删删

给定一个字符串,你可以删除多个(可以是 00) 相同 的字符,这样操作之后,你能否得到一个回文串?如果能,求最小化删除的个数。

输入格式

多组数据。

每一组数据包含两行,分别为字符串的长度 N,以及一个仅由小写字母组成的字符串 S。

输出格式

对于每一组数据,输出一行。

如果不可能得到一个回文串,输出 −1−1。反之则输出最小操作次数。

样例输入
4
8
bilibili
3
qwq
9
daimayuan
7
xcpcxpc
样例输出
1
0
-1
2

解释:

在第一个例子中,删除开头的 b 得到 ilibili

第二个例子中,qwq 本身已回文,不需要操作。

第三个例子中,可以看到 daimayuan 不能靠仅删除一种字符得到一个回文串。

数据规模
  • 1≤N≤105, 但保证 ∑N≤2×105
代码
#include<bits/stdc++.h>
using namespace std;
int n, tn;
string s;

int main(){
    scanf("%d", &n);
    while(n--){
        int res = INT_MAX;
        cin >> tn >> s;
        for(char i = 'a'; i <= 'z'; ++i){
            bool flag = true;
            int ans = 0, l = 0, r = tn - 1;
            while(l < r){
                //cout << "l: " << l << " r: " << r << "ans: " << ans <<  endl;
                if(s[l] == s[r])
                    l++, r--;
                else{
                    if(s[l] == i)
                        ans++, l++;
                    else if(s[r] == i)
                        ans++, r--;
                    else{
                        flag = false;
                        break;
                    }
                        
                }
            }
            if(flag)
                res = min(res, ans);
        }
        if(res == INT_MAX)
            printf("-1\n");
        else
            printf("%d\n", res);
    }
    
    //system("pause");
    return 0;
}

快快变大

给定一个长度为 n 的数组 a1,a2,…,an,接下来进行 n−1次操作。每次选择一个下标 x ,将 ax 和 ax+1 合并成 ax×ax+1mod1000003 ,并且你会获得 (ax−ax+1)2 的分数。

所以每次操作后,数组的长度将会减 11,当最后只剩下一个元素时停止操作。输出最终能获得的最大分数。

输入格式

第一行一个数字 n。

接下来一行 n 个整数 a1,a2,…,an。

输出格式

一个数,表示答案。

样例输入
3
1 2 3
样例输出
26
数据规模

所有数据保证 1≤n≤300,1≤ai≤106

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

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;
}

int main()
{
    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;
}

饿饿 饭饭2

接着《饿饿 饭饭》 的故事,在两天后,食堂的工作人员回来了,整个食堂又回到了原来井井有条的状态。

两个月后,由于天气越来越热,大家的胃口越来越小了,作为食堂管理员的CC非常担心孩子们的身体健康,所以他决定开展一个活动来调动孩子们吃饭的积极性,顺便考验一下孩子们的数学水平。活动内容如下:

先让每一个孩子都抽一个球,每一个球上有一个数字, 然后给这个孩子n个数字,每一个孩子都有无数次操作机会,每一次都会选中一个数将它乘上22,或者乘上33,请问这个孩子可以通过上面的操作将这n个数都变成相同的吗?

如果回答正确,这个回答正确的孩子就可以得到一份免费的午餐,但是这对于孩子们来说是在是太困难了,但是他们都想吃到免费的午餐,所以他们都想请你告诉他们正确的答案,让他们都迟到免费的午餐。

输入格式

第11行给定一个数T,表示有T个小孩子请你告诉他正确的答案。

第22到T+1行,第11个数是每个孩子抽到的数字n,第22到n+1个数是对应的n个数字。

输出格式

如果可以变成相同的,输出YES。如果不能变成相同的,输出NO

数据规模

1≤T≤100,1≤n≤2×105,1≤ai≤109

数据保证∑Ti=1n≤2×105

样例输入
2
4 75 150 75 50
3 100 150 250
样例输出
YES
NO
代码
#include<bits/stdc++.h>
using namespace std;

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;
}

int main()
{
    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;
}

子串分值和

对于一个字符串 S,我们定义 f(S) 为 S中出现的不同的字符个数。 例如 f(aba)=2,f(abc)=3,f(aaa)=1。

现在给定一个字符串 S (假设长度为 len),请你计算 ∑i=0len−1∑j=ilen−1f(S[i:j]) 。

输入格式

输入一行包含一个由小写字母组成的字符串 S。

输出格式

输出一个整数表示答案。

样例输入
ababc
样例输出
28
数据规模

所有数据保证字符串长度 len≤1000000,字符串下标从 00 到 len−1。

代码
#include <iostream>
using namespace std;

typedef long long LL;

int last[200];

int 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;
}

蒟蒻

便利蜂的货架上摆了一排蒟蒻果冻,搞得鶸尛鱻眼花缭乱…

对于每个果冻,都有一个价格 w和口感 t。鶸尛鱻有一个购物篮子,在挑选蒟蒻果冻的时候,他有以下几种操作:

  • 操作 11:把一个价格为 w,口感为 t 的果冻放入篮子。
  • 操作 22:拿出篮子中 最为廉价 的果冻。
  • 操作 33:拿出篮子中 口感最差 的果冻。(t 越小,口感越差)

鶸尛鱻不喜欢重复,当操作 11 的 价格或口感 与篮中已有果冻重复时,他会立刻将其放回货架。

经过 n 次操作后,鶸尛鱻确定了要购买的若干果冻,请你帮他求出篮子里果冻的总价格。

输入格式

第 11 行一个正整数 n,代表操作次数。

第 22 行至第 (n+1) 行,每行 一个或三个 整数,分别表示 op。

w和 t 当且仅当 op=1 时存在。

输出格式

输出一个整数,表示篮子里果冻的总价格。

样例输入
6
1 1 1
1 2 5
2
1 3 3
3
1 5 2
样例输出
7
数据规模

所有数据保证 1≤n≤105,1≤w,t≤106,且保证输入合法

代码
#include<bits/stdc++.h>
using namespace std;
int n, ans = 0;
pair<long, long> a[505];
set<pair<long long, long long>> m;

long long gcd(long long x, long long y){
    if(x < y){
        int t = x;
        x = y;
        y = t;
    }
    int z = y;
    while(x % y != 0){
        z = x % y;
        x = y;
        y = z;
    }
    return z;
    // return y ? gcd(y, x % y) : x;
}

int main(){
    //memset(m, 0, sizeof(m));
    scanf("%d", &n);
    for(int i = 0; i < n; ++i){
        scanf("%d%d", &a[i].first, &a[i].second);
    }
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            if(i == j)
                continue;
            long long x = a[i].first - a[j].first;
            long long y = a[i].second - a[j].second;
            long long k = gcd(x, y);
            //cout << "k: " << k << " x / k " << x/k << " y / k " << y/k << endl;
            m.insert({x/k, y/k});
        }
    }
    printf("%d", m.size() * 2);
    system("pause");
    return 0;
}

锦标赛

题目描述

有n个玩家参加比赛,他们分别有能力值a1,a2,…,an。

需要进行n−1轮比赛,每一轮在剩下的玩家里任选两个玩家i,j。如果|ai−aj|>K,那么其中能力值高的玩家会获胜,能力值低的玩家会被淘汰。如果|ai−aj|≤K,那么两个玩家都有可能获胜,另一个玩家被淘汰。

n−1�−1轮比赛之后,只剩下一个玩家。问有多少个玩家可能是最后获胜的玩家。

输入格式

第一行,两个整数n,K,表示玩家的总人数,和获胜条件中的参数。

接下来一行n个整数a1,a2,…,an,表示玩家的能力值。

输出格式

一个整数,表示最后可能获胜的玩家个数。

样例输入1
5 3
1 5 9 6 3
样例输出1
5
样例输入输出2

见下发文件。

数据规模

共10组数据。

测试点11满足n≤5。

测试点22满足n≤10。

测试点3,4,53,4,5满足n≤1000。

对于100%100%的数据,满足n≤105,1≤ai,K≤109。

代码
#include<bits/stdc++.h>
using namespace std;
int n;
char s1[1005], s2[1005];

int main(){
    scanf("%d", &n);
    while(n--){
        scanf("%s%s", s1, s2);
        if(strlen(s1) != strlen(s2)){
            printf("NO\n");
            continue;
        }
        int a = 0, b = 0;
        for(int i = 0; i < strlen(s1); ++i){  
            if(s1[i] - '0' == 1)
                a++;
            if(s2[i] - '0' == 1)
                b++;
        }
        if((a == 0 && b != 0) ||(a != 0 && b == 0) )
            printf("NO\n");
        else 
            printf("YES\n");
    }
    system("pause");
    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
数据规模

对于 100%100% 的数据,保证 1≤n≤9,1≤pi≤9,保证满足条件的序列个数不超过 105105 个。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int k;
ll a = 0, res = 0, ans = 0;
string s;
map<int, int> m;
int num[maxn] ={0}, pre[maxn] = {0};


int main(){
    m[0]++;
    scanf("%d", &k);
    cin >> s;
    if(k == 0){
        ans = 0;
        s += '1';
        for(int i = 0; i <= s.length(); ++i){
            if(s[i] == '0')
                ans++;
            else{
                res += (ans + 1) * ans / 2;
                ans = 0;
            }
        }
    }
    else
    {
        for(int i = 1; i <= s.length(); ++i){
        num[i] = s[i - 1] - '0';
        pre[i] = num[i] + pre[i - 1];
        m[pre[i]]++;
        }
        ans = 0;
        // for(auto t : m){
        //     cout << t.first << " " << t.second << endl;
        // }
        // for(int i = 0; i <= s.length(); ++i)
        //     cout << "pre[" << i << "]: " << pre[i] << endl;
        while(m[k + ans] != 0){
            //cout << ans << " " << ans + k << " " << pre[ans] << " " << pre[ans + k] << endl;
            res += (m[ans] * m[ans + k]);
            //cout << res << endl;
            ans++;
        }
    }
    cout << res << endl;
    system("pause");
    return 0;
}

进制转换

题面

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


以不同进制的形式输入 n 个非负整数,求出它们的和并以 m 进制的形式输出。

使用大写字母 A ~ Z 依次代表 1010 ~ 3535, 小写字母 a ~ z 依次代表 3636 ~ 6161。

输入格式

第一行输入两个整数 1≤n≤10 , 2≤m≤62 。

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

输出格式

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

输入样例1
2 2
2 1
6 10
输出样例1
111
输入样例2
1 10
52 aA0
输出样例2
97864
输入样例3
2 52
36 AMD
52 YES
输出样例3
dJD
代码
#include<bits/stdc++.h>
using namespace std;
int n, arr[100005], top, cur, cnt;  //top 记录栈顶元素
//stack<int> st;

int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; ++i)
        scanf("%d", &arr[i]);
    top = 0;
    cur = 0;
    cnt = 1;
    for(int i = 0; i < 2 * n; ++i){
        if(top < arr[cur]){
            printf("push %d\n", cnt);
            top = cnt;
            cnt++;
        }
        else if(top == arr[cur]){
            printf("pop\n");
            cur++;
        }
        else{
            printf("pop\n");
            cur++;
        }
    }
    system("pause");
    return 0;
}

循环子串

题目描述

一个字符串S是另一字符串T的循环子串当且仅当存在k, T所有字符循环右移k位后得到的新串T,满足S是T的子串。

例如: abccefab的循环子串。 (cefab循环右移22位得到abcef, abcabcef的子串)

一个串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
提示 选中可以查看
代码
#include<bits/stdc++.h>
using namespace std;
typedef struct node{
    int num;
    node* next;
}node;
node* head;
int n, a, b;
string s;

void insert(int index, int number){
    node* temp = new node;
    temp->num = number;
    node* cur = head;
    while(index--){
        cur = cur->next;
    }
    temp->next = cur->next;
    cur->next = temp;
}

void deleteNode(int index){
    node* cur = head;
    while(--index){
        cur = cur->next;
    }
    cur->next = cur->next->next;
    //delete(cur->next);
}

void query(int index){
    node* cur = head;
    while(index--){
        cur = cur->next;
    }
    printf("%d\n", cur->num);
}

int main(){
    node *cur = new node;
    cur->num = 0;
    cur->next = nullptr;
    head = cur;
    scanf("%d", &n);
    while(n--){
        cin >> s;
        if(s == "insert"){
            scanf("%d%d", &a, &b);
            insert(a, b);
        }
        else if(s == "delete"){
            scanf("%d", &a);
            deleteNode(a);
        } 
        else{
            scanf("%d", &a);
            query(a);
        }
    }
    system("pause");
    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;

int main()
{
    int n;
    cin >> n;
    vector<int>s(n + 1);
    vector<vector<char>>v(n + 1, vector<char>(n + 1));
    string str;
    for (int i = 1; i <= n; i++)
    {
        cin >> str;
        for (int j = 1; j <= n; j++)
        {
            v[i][j] = str[j - 1];
            s[j] = s[j - 1];
            if (str[j - 1] == 'W')s[j] += 1;
            if (j >= 4&&(s[j]==s[j-3]||s[j]-s[j-3]==3))
            {
                cout << 0 << endl;
                return 0;
            }
        }
        if (s[n] != n / 2)
        {
            cout << 0 << endl;
            return 0;
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            s[j] = s[j - 1];
            if (v[j][i] == 'W')s[j] += 1;
            if (j >= 4 && (s[j] == s[j - 3] || s[j] - s[j - 3] == 3))
            {
                cout << 0 << endl;
                return 0;
            }
        }
        if (s[n] != n / 2)
        {
            cout << 0 << endl;
            return 0;
        }
    }
    cout << 1 << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值