【套题】牛客练习赛21

黑妹的游戏I

题意

黑妹最近在玩一个有趣的游戏,游戏规则是这样的:
刚开始黑板上有三个不同的初始数字,然后黑妹每一次可以选择黑板上的两个不同的数字,然后计算出这两个不同数字之差的绝对值,如果黑板上没有这个数字,那么就把这个新数字写在黑板上。
黑妹已经玩腻了这个游戏,现在黑妹想知道她最多能添加多少个数字。

题解

计算gcd。
如果gcd为1,那么可以制造出 m a x ( a , b , c ) 3 个元素,否则制造出 m a x ( a , b , c ) / g c d ( a , b , c ) 3 个元素。
这里abc三个数不同,我考虑相同的情况,多此一举了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
set<ll> s;
ll a,b,c;
int main() {
    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld%lld",&a,&b,&c);
        s.clear();
        s.insert(a), s.insert(b), s.insert(c);
        ll g = __gcd(a,__gcd(b,c));
        if(s.size() == 1) printf("0\n");
        else{
            if(g == 1) printf("%lld\n",max(a,max(b,c)) - (ll)s.size());
            else printf("%lld\n",max(a,max(b,c)) / g - (ll)s.size());
        }
    }
    return 0;
}

黑妹的游戏II

题意

黑妹和黑弟又聚在一起玩游戏了,这次他们选择在一个n*m的棋盘上玩游戏,棋盘上的每个方格都有一个非负的分数,
游戏从左上角开始右下角结束,双方交替的选择一个方格并获得方格上相应的分数,一方选择的方格必须在上一步另一方选择的方格
的右边或者下面,黑妹先开始。现在黑妹想知道,如果双方都采取最优策略(最优策略是指双方都希望最终自己的总分数减去对方的总分数最大),她的总分数减去黑弟的总分数会是多少?

题解

DP
d p [ i ] [ j ] 表示从 < i , j > 走到 < n , m > 能比多方多的分数值。
则状态转移方程为 d p [ i ] [ j ] = a [ i ] [ j ] m a x ( d p [ i + 1 ] [ j ] , d p [ i ] [ j + 1 ] ) .
注意对于一个给定的n,m,两人格子的选择实际是交替的,这并不与dp方程冲突。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int nmax = 505;
int t,n,m;
ll dp[nmax][nmax],a[nmax][nmax];
int main() {
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i = 1;i<=n;++i) for(int j = 1;j<=m;++j) scanf("%lld",&a[i][j]),dp[i][j] = 0;
        dp[n][m] = a[n][m];
        for(int i = m-1;i>=1;--i) dp[n][i] = a[n][i] - dp[n][i+1];
        for(int i = n-1;i>=1;--i) dp[i][m] = a[i][m] - dp[i+1][m];
        for(int i = n-1;i>=1;--i) for(int j = m-1;j>=1;--j) dp[i][j] = a[i][j] - max(dp[i][j+1],dp[i+1][j]);
        printf("%lld\n",dp[1][1]);
    }
    return 0;
}

黑妹的游戏III

题意

黑妹又开始玩起了一个游戏,这次她面对的是一个序列,序列里的每个数字都是正整数,黑妹每次可以从这个序列里选择两个数字,然后将这两个数字除以它们任意一个公共因子。
如果 x 是 a 和 b 的公共因子,当且仅当 a 和 b 都能被 x 整除。
黑妹很快玩腻了这些操作,她现在想知道,这个序列经过一些操作之后,将新序列的每个元素都乘起来的最小乘积是多少,由于这个乘积可能很大,所以你需要告诉黑妹这个乘积对109+7取模之后的值。

题解

将每个数字因式分解,每次拿掉数字中的公共因子部分,将所剩下的因子乘积即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int nmax = 1e5+10;
int n,m,t,pri[nmax+100],data[nmax+100];
vector<int> v;
priority_queue<int> pq;
inline void init(){
    for(int i = 2;i<=10000;++i){
        if(pri[i] == 1) continue;
        v.push_back(i);
        for(int j = i+i;j<=10000;j+=i) pri[j] = 1;
    }
}
int main() {
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ll ans = 1;
        for(int i = 1;i<=n;++i) scanf("%d",&data[i]);
        for(int i = 0;i<v.size();++i){
            int cnt = 0; 
            for(int j = 1;j<=n;++j){
                cnt = 0;
                while(data[j] % v[i] == 0) data[j] /= v[i], cnt++;
                if(cnt>0) pq.push(cnt);
            }
            while(pq.size() > 1){
                int t1 = pq.top();pq.pop();
                int t2 = pq.top();pq.pop();
                t1--; t2--;
                if(t1>0) pq.push(t1);
                if(t2>0) pq.push(t2);
//                t1-=t2;
//                if(t1>0) pq.push(t1);
            }
            cnt = 0;
            if(!pq.empty()) {cnt = pq.top(); pq.pop();}
            while(cnt){ans = (ans * v[i])  % MOD; cnt--;}
        }
        sort(data+1,data+1+n);
        for(int i = 1;i<=n-1;++i) if(data[i] == data[i+1]) data[i] = data[i+1] = 1;
        for(int i = 1;i<=n;++i) ans = (ans * data[i]) % MOD;
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/80956055