• 2019牛客暑期多校第一场题解ABCEFHJ


    A.Equivalent Prefixes

    传送门

    题意:给你两个数组,求从第一个元素开始到第p个元素 满足任意区间值最小的元素下标相同的 p的最大值。

    题解:我们可以从左往右记录到i为止每个区间的最小值有哪些,因为每个值都是不一样的,对于当前的 i 如果1~i中每个区间最小值数量相同那么下标肯定也会相同,否则记录的值的数量就会不同,我们可以用单调栈记录目前为止每个区间的“最小值”的下标,栈里面元素数量不同时肯定不满足条件。

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 1e5 + 10;
    int a[N],b[N],u[N],v[N];
    int main() {
        int n;
        while(~scanf("%d",&n)) {
            for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
            for (int i = 1; i <= n; i++) scanf("%d",&b[i]);
            int i,cnt1=0,cnt2=0;
            for ( i = 1; i <= n; i++) {
                while (cnt1 && a[i] < a[u[cnt1]]) cnt1--;
                u[++cnt1] = i;
                while (cnt2 && b[i] < b[v[cnt2]]) cnt2--;
                v[++cnt2] = i;
                if (cnt1 != cnt2) break;
            }
            printf("%d
    ", i-1);
        }
        return 0;
    }
    View Code

    B.Integration

    传送门

    题意:已知输出

    题解:

     

    参考博客: https://blog.csdn.net/mmk27_word/article/details/96450520

          https://www.cnblogs.com/yanlifneg/p/11211455.html#commentform

    代码: 

    #include <cstdio>
    #include <cstring>
    #define ll long long
    using namespace std;
    const int N = 1000 + 10;
    const ll mod = 1e9 + 7;
    ll a[N],b[N];
    ll qp(ll a,ll b) {
        ll ans = 1;
        a%=mod;
        while(b) {
            if (b&1) ans = ans * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return ans;
    }
    int main() {
        int n;
        while(~scanf("%d",&n)) {
            for (int i = 0; i < n; i++)
                scanf("%lld",&a[i]);
            ll ans = 0;
            for (int i = 0; i < n; i++) {
                b[i] = 2 * a[i] % mod;
                for (int j = 0; j < n; j++)
                    if (i != j) b[i] = b[i] * ((a[j]*a[j]-a[i]*a[i])%mod) %mod;
                b[i] = qp(b[i],mod-2);
                ans = ((ans + b[i]) % mod + mod) % mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    C.Euclidean Distance

    传送门

    题意:在一个n维坐标系里面有个点A(a1/m,a2/m,...,an/m),在坐标系中找到一个点P(p1,p2,...,pn)满足pi>0且∑ni=1 pi =1,求满足条件的P到A的

    最小欧几里得距离ni=1​ (ai/mpi)^2

    题解:为了方便计算我们可以先约去m最后再将结果除以m^2,就成了求∑ni=1​ (aipi)^2 /m^2,∑ni=1 pi =m。显然我们减小数值大的ai的值比减小值小的ai更优。

    我们先将ai排序,为了使得最大值更小,我们可以每次把最大值更新到与下一个值相同大小。我们初始化能更新到的数组长度num = n,可以用来减小ai的值have = m。

    如果have的值能够将前i个元素更新为a[i+1]则更新;否则num更新为i,剩余的have平分到前num个元素上,此时前num个元素的值都是a[num]-have/num。剩下的n-num个元素值为ai。

    此时∑ni=1​ (aipi)^2 /m^2 =(num*(a[num]-have/num)^2+∑ni=num+1a[i]^2)/m^2。

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 1e4 + 10;
    const int M = 70;
    const ll mod = 1e9 + 7;
    int a[N];
    int main() {
        int n,m;
        while(~scanf("%d%d",&n,&m)) {
            for (int i = 1; i <= n; i++) {
                scanf("%d",&a[i]);
            }
            sort(a+1,a+n+1,greater<int>());
            int num = n,have = m;
            for (int i = 1; i < n; i++) {
                if (i* (a[i]-a[i+1])<= have)
                    have -= i*(a[i]-a[i+1]);
                else {
                    num = i;
                    break;
                }
            }
            ll fm = 1ll * num * m * m;
            ll fz = (1ll*a[num]*num - have) * (1ll*a[num]*num - have) ;
            for (int i = num+1; i <= n; i++)
                fz += 1ll*num*a[i]*a[i];
            ll tf = __gcd(fz,fm);
            fz/=tf;fm/=tf;
            if (fm == 1 ) printf("%lld
    ", fz);
            else printf("%lld/%lld
    ", fz,fm);
        }
        return 0;
    }
    View Code

     

    E:ABBA

    传送门

    题意:有一个长度2(n+m)的字符串,它可以被分解成n个AB,m个BA,问有多少种符合条件的字符串,答案% 10^9+7

    题解:贪心,我们先用AB的A,再用BA的B,B同理。我们可以用dp[i][j]表示用了i个A和j个B组成合法序列的方案数,因为我们先用AB的A(AB有n个),再用BA的A,所以A的数量最多可以有B的数量+n个,当A的数量没这么多时可以在字符串中加个A,即 if (i-j<n) dp[i+1][j] = (dp[i+1][j]+dp[i][j])%mod; B同理。

     代码:

    #include <cstdio>
    #include <cstring>
    #define ll long long
    using namespace std;
    const int N = 2000 + 10;
    const ll mod = 1e9 + 7;
    ll dp[N][N];
    int main() {
        int n,m;
        while(~scanf("%d%d",&n,&m)) {
             for (int i = 0; i <= n+m; i++)
                for (int j = 0; j <= n+m; j++) dp[i][j] = 0;
            dp[0][0] = 1;
            for (int i = 0; i <= n+m; i++)
                for (int j = 0; j <= n+m; j++) {
                    if (i-j<n) dp[i+1][j] = (dp[i+1][j]+dp[i][j])%mod;
                    if (j-i<m) dp[i][j+1] = (dp[i][j+1]+dp[i][j])%mod;
                }
            printf("%lld
    ",dp[n+m][n+m]);
        }
        return 0;
    }
    View Code

    F:Random Point in Triangle

    传送门

    题意:在△ABC中任选一个点P,P与A、B、C三点相连,求最大的面积的期望E = max{S△PBC,S△APC,S△ABP} * 36的结果。

    题解:E= 11/36 * S△ABC => 36E = 11 S△ABC

    证明参考:https://www.cnblogs.com/WAautomaton/p/11211864.html

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int main() {
        ll x1,x2,x3,y1,y2,y3;
        while(~scanf("%lld%lld%lld%lld%lld%lld",&x1,&y1,&x2,&y2,&x3,&y3))
            printf("%lld
    ", abs(11*(x1*y2+x2*y3+x3*y1-x1*y3-x3*y2-x2*y1)));
        return 0;
    }
    View Code

    H.XOR

    传送门

    题意:给你一个有n个元素的集合a,问a的异或和为0的所有子集的元素数量和。

    题解:我们可以转化为求每个数能异或为0的贡献。这里要用到线性基 <--- 推荐博客。

       我们先求集合a的线性基A,A中元素数量为r,对于线性基外n-r个元素,任选一个还剩n-r-1个,那么这n-r个元素每个的贡献为2^(n-r-1);

     然后我们考虑线性基内的元素x,我们对剩下n-1个数求线性基,避免超时我们先对线性基A外的n-r个元素求线性基B,然后在计算线性基A内各个元素x的贡献时,将B数组赋值给C再将A内其他元素加入C内,如果x加不进则求x的贡献。

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 1e5 + 10;
    const int M = 70;
    const ll mod = 1e9 + 7;
    ll a[N],b[N],A[M],B[M],C[M];
    bool add(ll arr[],ll x) {
        for (int i = 63; i >= 0; i--) {
            if (x & (1ll<<i)) {
                if (arr[i]) x^=arr[i];
                else {
                    arr[i] = x;
                    return true;
                }
            }
        }
        return false;
    }
    ll qp(ll y){
        ll ans = 1,x = 2;
        while(y) {
            if (y&1) ans = ans*x%mod;
            x = x * x % mod;
            y>>=1;
        }
        return ans;
    }
    int main() {
        int n;
        while(~scanf("%d",&n)) {
            memset(A,0,sizeof(A));
            memset(B,0,sizeof(B));
            int r = 0;
            for (int i = 0; i < n; i++) {
                scanf("%lld",&a[i]);
                if (add(A,a[i])) b[r++] = a[i];
                else add(B,a[i]);
            }
            if (r == n) {
                printf("0
    ");
                continue;
            }
            ll ans = (n-r) * qp(n-r-1) %mod;
            for (int i = 0; i < r; i++) {
                for (int j = 0; j <= 63; j++) C[j] = B[j];
                for (int j = 0; j < r; j++)
                    if (i!=j) add(C,b[j]);
                if (!add(C,b[i])) ans = (ans + qp(n-r-1)) % mod;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code

    J.Fraction Comparision

    传送门

    题意:比较x/a和y/b的大小关系。

    题解:因为 0≤ x,10^18,所以我们可以先比较整数部分,当整数部分相同时再把余数交叉相乘比较大小。

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 64 + 10;
    int main() {
        ll x,y,a,b;
        while(~scanf("%lld%lld%lld%lld",&x,&a,&y,&b)) {
            ll t1 = x/a, t2 = y/b;
            if (t1 < t2) printf("<
    ");
            else if (t1 > t2) printf(">
    ");
            else {
                t1 = x%a*b;
                t2 = y%b*a;
                if (t1 < t2) printf("<
    ");  
                else if (t1 > t2) printf(">
    ");
                else if (t1 == t2) printf("=
    ");
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    iPhone 12 Pro 不锈钢边框刮伤 All In One
    .vscodeignore All In One
    程序员如何挑选和购买一款高性价比的电动升降桌 All In One
    TypeScript function arguments destructuring All In One
    LeetCode 旋转数组算法题解 All In One
    python 中实现DNA一致性序列计算
    python中输出两条长度一致序列碱基不同的个数
    python 中统计不同scafflod的GC含量并输出GC含量最高的scafflod
    python 中 斐波那契兔子问题
    python 中如何将列表中的数值转换为字符串
  • 原文地址:https://www.cnblogs.com/l999q/p/11279400.html
Copyright © 2020-2023  润新知