黑妹的游戏I
题意
黑妹最近在玩一个有趣的游戏,游戏规则是这样的:
刚开始黑板上有三个不同的初始数字,然后黑妹每一次可以选择黑板上的两个不同的数字,然后计算出这两个不同数字之差的绝对值,如果黑板上没有这个数字,那么就把这个新数字写在黑板上。
黑妹已经玩腻了这个游戏,现在黑妹想知道她最多能添加多少个数字。
题解
计算gcd。
如果gcd为1,那么可以制造出
个元素,否则制造出
个元素。
这里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
表示从
走到
能比多方多的分数值。
则状态转移方程为
.
注意对于一个给定的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;
}