【牛客练习赛64】前三题题解

A

解法:贪心,构造
题意:给定了n个1,m个2,k个4,构造一个n+m+k的序列,求1412的子序列最多个数。
思路:很显然,将1分为两堆,把所有的4都放进两堆的中间,所有的2放在最右边时,能获得最多的1412子序列个数,例如1412,1144112,144122,...

最终输出
代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

inline char nc()
{
    static char buf [100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    static char c=nc();
    int x=0,f=1;
    for(;c>'9'||c<'0';c=nc())
        if(c=='-') f=-1;
    for(;c<='9'&&c>='0';c=nc())
        x=(x<<3)+(x<<1)+c-48;
    return x*f;
}


const int N = 2e1 + 10;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;


int main()
{
    // std::ios::sync_with_stdio(false);
    // std::cin.tie(0);
    int t;
    LL n, m, k, ans;
    cin >> t;
    while(t--){
        cin >> n >> m >> k;
        ans = 0;
        if(n < 2|| m < 1|| k < 1)    //这一步其实不必要
            cout << 0 << endl;
        else{
            LL tmp = n / 2;
            n -= tmp;
            ans = n * tmp * m * k;
            cout << ans << endl;
        }
    }
    return 0;
}

B

思路:统计每一个点的度数,那么距离该点为2的个数为与它相连的点的度数减1之和或者说与它相连的点的度数之和减去相连点的个数。
代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

inline char nc()
{
    static char buf [100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    static char c=nc();
    int x=0,f=1;
    for(;c>'9'||c<'0';c=nc())
        if(c=='-') f=-1;
    for(;c<='9'&&c>='0';c=nc())
        x=(x<<3)+(x<<1)+c-48;
    return x*f;
}

const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int tree[N];
struct node{
    int x, y;
}root[N];
LL ans[N];

int main()
{
    // std::ios::sync_with_stdio(false);
    // std::cin.tie(0);
    int t, x, y;
    cin >> t;
    for(int i = 1;i < t;i++){
        cin >> root[i].x >> root[i].y;
        tree[root[i].x]++;
        tree[root[i].y]++;
    }
    for(int i = 1;i < t;i++){
        ans[root[i].x] += tree[root[i].y] - 1;
        ans[root[i].y] += tree[root[i].x] - 1;
    }
    for(int i = 1;i <= t;i++)
        cout << ans[i] << endl;
    return 0;
}

C

解法:数学
思路:看到这条式子 ,第一反应可能会觉得头大。那么来化简一下。

假设

时,可以写出

化简一下就得到,

同理,时,可以得到

就有

就有
整理一下变成

可以发现这个式子就变成了

那么这道题就完成了,可以用前缀和来处理

代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

inline char nc()
{
    static char buf [100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    static char c=nc();
    int x=0,f=1;
    for(;c>'9'||c<'0';c=nc())
        if(c=='-') f=-1;
    for(;c<='9'&&c>='0';c=nc())
        x=(x<<3)+(x<<1)+c-48;
    return x*f;
}

const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
LL a[N];
LL b[N];
LL s[N];

int main()
{
    // std::ios::sync_with_stdio(false);
    // std::cin.tie(0);
    // freopen("1.in","r", stdin);
    // freopen("out.out","w", stdout);
    LL n, ans = 0;
    cin >> n;
    s[0] = 0;
    for(LL i = 1;i <= n;i++){
        cin >> a[i];
        b[i] = ((n-i+1) * a[i]) % MOD;     //求(n-i+1)*ai
        s[i] = (b[i] + s[i-1]) % MOD;    //前缀和处理
    }
    for(LL i = 1;i <= n;i++){
        LL cnt = s[n] - s[i-1] + MOD; 
        /*血泪教训,因为在计算前缀和的时候取了模,那么前缀和数组里的数组不再成单调,就可能最后一项减去i-1项时出现负数,导致最后结果算错,加上1个MOD就能处理掉负数的情况*/
        ans = (ans + (i * (a[i] * cnt % MOD) % MOD) % MOD) % MOD;
    }
    cout << ans << endl;
    return 0;
}
全部评论
C题 l=1的时候,博主应该笔误少写了 a1乘的那部分 少了r=3的情况
1 回复 分享
发布于 2020-05-22 23:04

相关推荐

评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务