2020牛客寒假算法基础集训营2

A签到 不说了

B
牛可乐 最喜爱的字符串是 \text{616}616。

牛可乐得到了一个纯数字的字符串 \text{}SS,他想知道在可以任意打乱 \text{}SS 顺序的情况下,最多有多少个不同的子串为 \text{616}616 。


时它们被认为是不同的。
输入描述:
第一行,一个正整数 |S|,表示 S 的长度。
第二行,一个字符串 S,其字符集为 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}。
保证 1 ≤ |S| ≤ 2 × 10^51≤∣S∣≤2×10
5

输出描述:
输出一行,一个整数表示答案。
示例1
输入

复制
11
11451419266
输出

复制
1
说明

一种最优打乱方案为 “11451492616”,有一个子串为 “616” 。

题意:就是找有多少个616 左端点不相等或者右端点不相等 均被认为是不同的子串 只要想到有61616 是两个子串就行了

比赛代码写麻烦了 其实答案就是 min(6的个数-1,1的个数)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>

using namespace std;
typedef long long LL ;

#define fi first
#define se second

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double pi=acos(-1);

const int N = 1e4+5;
const int mod = 1e9+7;

LL vis[5];

int main()
{

    int n;

    string s;

    cin >> n;

    cin >> s;

    for(int i = 0;i < n;i ++)
    {
        if(s[i] == '6')
            vis[0] ++;
        if(s[i] == '1')
            vis[1] ++;
    }


    if(vis[0] > vis[1])
        cout << vis[1] << '\n';
    else if(vis[0] == vis[1])
    {
        if(vis[0] > 2)
            cout << vis[1]-1 << '\n';
        else if(vis[0] == 2)
            cout << '1' << '\n';
        else
            cout << '0' << '\n';
    }
    else
        cout << vis[0] - 1 << '\n';


    return 0;
}

C.
题意:输入n道题的正确的概率 对1e9+7取模 存在逆元
n 题里恰好有 0~n 题正确的概率分别是多少
对于一个不可约分的分数 a/b 存在q使得 b*q mod 1e9+7 = a 那么 q 就是 a/b对 1e9+7取模的结果

思路:跑一遍概率dp即可
dp[i][j 表示前i道题做对j题的概率

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>

using namespace std;
typedef long long LL ;

#define fi first
#define se second

const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);

const int N = 2005;
const int mod = 1e9+7;

LL dp[N][N];
LL p[N];

int main()
{
    int n;

    cin >> n;

    for(int i = 1;i <= n; i ++)
    {
        cin >> p[i];
    }

    dp[0][0] = 1;

    for(int i = 1;i <= n;i ++)
    {
        dp[i][0] = dp[i-1][0]*(mod+ 1 - p[i])%mod;///对逆元的处理

        for(int j = 1;j <= i; j ++)
        {
            dp[i][j] = (dp[i-1][j]*(mod + 1 - p[i])+dp[i-1][j-1]*p[i])%mod;
        }
    }

    for(int i = 0;i <= n;i ++)
        cout << dp[n][i] << ' ';

    return 0;
}

D.
题意给出n个点 求n个点能构成钝角三角形的个数

思路:n范围不大 直接暴力枚举3个顶点即可 然后判断是否构成三角形 和 是否是钝角三角形即可

这边注意全开double 如果写的太挫的话 可能会因为常数太大而T掉 并且 判断浮点数的是否相等记得补精度
<= eps 就认为是相等的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
 
using namespace std;
typedef long long LL ;
 
#define fi first
#define se second
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
 
const int N = 1e4+5;
const int mod = 1e9+7;
 
 
struct node
{
    LL x,y;
}arr[505];
 
LL cal(LL x,LL y,LL xx,LL yy)
{
    LL sum = 1LL*(xx-x)*(xx-x)+(yy-y)*(yy-y);
 
    return sum;
}
 
 
int main()
{
    int n;
 
    scanf("%d",&n);
 
    for(int i = 0;i < n;i ++)
        scanf("%lld%lld",&arr[i].x,&arr[i].y);
 
    int res = 0;
 
    LL a,b,c;
    int i,j,k;
 
    for(i = 0;i < n; ++ i)
    {
        for(j = i+1; j < n; ++ j)
        {
            for(k = j+1; k < n;++ k)
            {
                 if((arr[j].x-arr[i].x)*(arr[j].y-arr[k].y) == (arr[i].y-arr[j].y)*(arr[j].x-arr[k].x))
                 ///计算斜率从而判断是不是共线
                     continue;
                 a = cal(arr[i].x,arr[i].y,arr[j].x,arr[j].y);
                 b = cal(arr[i].x,arr[i].y,arr[k].x,arr[k].y);
                 c = cal(arr[j].x,arr[j].y,arr[k].x,arr[k].y);
 
               
                 if(a >= b && a >= c && a > b+c)
                     res ++;
                 else if(b >= a && b >= c && b > a+c)
                     res ++;
                 else if(c >= b && c >= a && c > a+b)
                     res ++;
            }
        }
    }
 
    printf("%d\n",res);
 
    return 0;
}

E.
题意:求n内有多少个三元组 i,j,k 满足 sqrt(i)+sqrt(j) = sqrt(k) && i*j < n

思路:两边平方得 i+j+2sqrt(ij) = k 因为都是整数 所以 ij 必须得是完全平方数 枚举完全平方数后求因子就行

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>

using namespace std;
typedef long long LL ;

#define fi first
#define se second

const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);

const int N = 1e4+5;
const int mod = 1e9+7;

int main()
{
    int n ;

    cin >> n;

    int res = 0;

    for(int i = 1; i*i <= n;i ++)
    {
        for(int j = 1; j <= i; j ++)
        {
            if(i*i % j == 0)
            {
                res += 2;
            }
        }

        res -= 1;/// 两个数相等的 算重复了 所以减去1
    }

    cout << res << '\n';

    return 0;
}

F

题意:有n个物品 有a,b两种属性 两个人轮流拿物品 一个以a属性算分 一个以b属性算分 问怎样差距能来到最大

思路:按a+b属性 排序 之后遍历即可 为什么是a+b 而不是a-b 可以这样想 如果a比较 大 那么 你直接获利更大 但如果b比较大 对方损失会更大 相对于你获利就多啦 差距就变大了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>

using namespace std;
typedef long long LL ;

#define fi first
#define se second

const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);

const int N = 2e5+5;
const int mod = 1e9+7;

struct node
{
    int a,b,id;
} arr[N];

bool cmp(node a,node b)
{
    return a.a+a.b > b.a + b.b;
}

vector<int>va,vb;

int main()
{
    int n;

    cin >> n;

    for(int i = 1; i <= n; i ++)
       cin >> arr[i].a;

    for(int i = 1; i <= n; i ++)
       cin >> arr[i].b,arr[i].id = i;

    sort(arr+1,arr+1+n,cmp);

    for(int i = 1;i <= n;i ++)
    {
        if(i&1)
            va.push_back(arr[i].id);
        else
            vb.push_back(arr[i].id);
    }

    for(auto i : va)
        cout << i << ' ';
    cout << '\n';

    for(auto i : vb)
        cout << i << ' ';
    cout << '\n';

    return 0;
}

G
题意:给你a b c d e f g 六个数 验证 在这里插入图片描述是否成立

思路:这题 有点玄学 正解是个随机取模数 然后我用快速幂 取模 1e9+7 就过了 但有的人过不了 可能写法不同

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>

using namespace std;
typedef long long LL ;

#define fi first
#define se second

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double pi=acos(-1);

const int N = 1e4+5;
const int mod = 1e9+7;
/// 998244353
LL quickpow(LL a,LL b)
{
    LL res = 1;

    while(b)
    {
        if(b&1)
            res = (res*a)%mod;

        b >>= 1;

        a = (a*a)%mod;
    }

    return res;
}

int main()
{
    LL a,b,c,d,e,f,g;

    int t;

    cin >> t;

    while(t -- )
    {
        cin >> a >> b >> c >> d >> e >> f >> g ;

        LL ax = quickpow(a,d);
        LL bx = quickpow(b,e);
        LL cx = quickpow(c,f);

        if(ax + bx + cx == g)
            cout << "Yes" ;
        else
            cout << "No" ;

        cout << '\n';
    }

    return 0;
}


贴个正解代码

#include <bits/stdc++.h>
using namespace std;
const int mod[] = {2, 3, 5, 7, 11, 31, 71, 97, 233, 397, 433, 449, 607, 857, 10007, 21179, 36251, 44579, 62003, 72883, 97843, 139991, 232013, 369353, 681521, 692711, 777241, 822821, 1956761, 2145137, 2915837, 6229117, 7788787, 13743493, 17331841, 19260817, 19269293, 19959809, 21006959, 23937083, 24410849, 28452757, 28478603, 29229359, 35570827, 35604011, 35875487, 37370863, 38303347, 38475517, 38819149, 40455791, 44021539, 45641993, 46531301, 48866749, 50529641, 52634191, 52790587, 55180799, 56971613, 58259351, 60954737, 62207269, 63367453, 65072599, 66017821, 67952779, 69475349, 74689217, 77059907, 77907121, 79391659, 84768797, 85584601, 85724879, 85756609, 86850899, 91783511, 92331541, 94519499, 96375241, 99033413, 99486311, 100569829, 106873549, 109329881, 109913681, 111186487, 111894067, 112136617, 112417363, 114011921, 119143363, 122994493, 123747781, 124001021, 126515639, 128191039, 128767909, 132222763, 133587661, 139644719, 145641527, 153388423, 155187077, 156883333, 157989581, 159538063, 161488643, 164039129, 166070447, 169181543, 169554227, 173564801, 175742867, 185469637, 187203899, 191263223, 198691817, 204144887, 211631201, 217903877, 218028203, 220073423, 228143453, 228667423, 232064653, 240519263, 245647159, 247586411, 247936121, 250949197, 253413211, 253464329, 260572729, 260590409, 262887773, 265711423, 266763641, 273585149, 276472817, 276500531, 280543667, 280649591, 281385491, 291366337, 293273159, 296973107, 302890501, 306568693, 315614297, 316729409, 317617121, 320337781, 320613497, 321322823, 324691051, 325963067, 327184157, 329900633, 330670159, 332058781, 332213669, 332300869, 334382221, 341895677, 347938237, 349011827, 349347503, 349906439, 353796941, 364557253, 364755931, 367946441, 372413831, 374358983, 379589897, 381149689, 389431873, 404683493, 405216109, 405495029, 408142403, 408989747, 410841979, 410935093, 412405351, 412592459, 412722139, 412990573, 418171483, 421270357, 424233613, 427938449, 428492083, 429962881, 430883569, 434988383, 435941201, 438816151, 440052953, 440143589, 444693631, 453646433, 455847109, 456640189, 457911511, 458185237, 463116761, 463861417, 469275953, 471298573, 471712513, 478267417, 483824813, 494828483, 497397293, 499657393, 507957479, 512906621, 519346459, 519879973, 520094713, 523213693, 525673273, 529575763, 529883803, 533887031, 534260809, 535328309, 541992667, 542253071, 544780177, 545567609, 552922529, 555129893, 555820037, 558473471, 563484017, 571310471, 578121241, 582251063, 583825639, 584121323, 592038487, 599098811, 601467677, 610073969, 615059213, 619220713, 622457177, 627412609, 630547919, 632342989, 637357363, 638865419, 648268013, 650007487, 651564761, 654115433, 661281713, 662664461, 667914281, 682988213, 691099121, 691445809, 692038043, 692411953, 698620943, 699007259, 701164631, 706806461, 707096251, 707697451, 709566589, 719095829, 725756807, 736880491, 739603867, 743026709, 744236861, 744396049, 747393791, 749395103, 760341121, 762934307, 773124059, 773195911, 776162609, 781629113, 781884613, 786120631, 788314343, 788898377, 788939293, 790209983, 791933183, 796328783, 798643889, 802280047, 803293991, 803847559, 809752739, 818520473, 820434047, 826810489, 829359959, 829707427, 836587463, 841011167, 843763253, 849410557, 851226437, 853058471, 853168793, 853778327, 859086391, 860720017, 863193077, 873061181, 888803059, 893035529, 900902953, 904636883, 917949577, 921817139, 922328707, 931449133, 933074827, 933156233, 935241721, 935632799, 939948881, 957119773, 961329913, 965269573, 965337949, 967551691, 971080093, 973578143, 976825877, 985100197, 985413691, 986124823, 990650057, 998244353, 999058883, 1000000007};
int ff(int a, int m) {
  return (a % m + m) % m;
}
int Pow(int a, int b, int c) {
  int ret = 1;
  while (b) {
    if (b & 1) ret = ret * 1ll * a % c;
    a = a * 1ll * a % c;
    b >>= 1;
  }
  return ret;
}
int a, b, c, d, e, f, g;
 
bool check(int m) {
  return ((Pow(ff(a, m), d, m) + Pow(ff(b, m), e, m)) % m + Pow(ff(c, m), f, m)) % m == ff(g, m);
}
 
int main() {
  int T;
  cin >> T;
  while (T--) {
    // cerr << T << endl;
    cin >> a >> b >> c >> d >> e >> f >> g;
    assert((a || d) && (b || e) && (c || f));
    assert(min(a, min(b, min(c, g))) >= -1e9 && max(a, max(b, max(c, g))) <= 1e9 && min(d, min(e, f)) >= 0 && max(d, max(e, f)) <= 1e9);
    bool flag = 1;
    for (int i = 0; i < 349; ++i) if (!check(mod[i])) {flag = 0; break;}
    puts(flag ? "Yes" : "No");
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值