1007.小猫钓鱼
题意:
一共有 2 n 2n 2n张牌, 1 1 1~ n n n的牌各有两张。
给定shuishui 和 sha7dow每人手上有 n n n张牌。
两人轮流出一张牌,按循序依次放好。
当一人A出的手牌在之前就出现过,那A可以把两张相同牌之间(包括两张一样)的牌都收为手牌。并获得等同于拿走牌数量的分数。
shuishui 先手操作,两人都想赢,问谁最后能获胜,或者平局。
题解:
两人手上都是单牌,显然不论先手打出什么,后手都可以出同样的单牌,直到先手的手牌为空,后手必胜。
两人都有双数牌时,先手先出单牌,后手就可以直接吃掉,没有意义。
先手出双牌,另外一人会减少一个双牌,先手+3分。所以后手一定会先没有手牌。先手必胜
代码:
csharp
#include <bits/stdc++.h>
#define int long long
#define PII pair<int,int>
using namespace std;
const int N =2e6+6;
int a[N],b[N];
int cnt[N];
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)cnt[i]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
cnt[a[i]]++;
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
int x=0,y=0;
for(int i=1;i<=n;i++){
if(cnt[i]==2)x++;
if(cnt[i]==1)y++;
}
if(x){
cout<<"shuishui\n";
}else{
cout<<"sha7dow\n";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
1005.怪物猎人
题意:
有一只怪兽生命值为 k k k,有两只宠物 a , b a,b a,b。
轮流对怪兽攻击,造成 x x x或者 y y y的伤害。
奇数轮 a a a攻击,偶数轮 b b b攻击。
问 a a a可能是最后一击吗, b b b可能是最后一击吗。
题解:
先假设 x < = y x<=y x<=y.
最多在 n n n轮怪兽死亡。即每次都用 x x x伤害攻击。
如果 y ∗ ( n − 1 ) > = k y*(n-1)>=k y∗(n−1)>=k:
一定可以在 n − 1 n-1 n−1轮怪兽死亡。两只宠物都可能是最后一击。
如果 y ∗ ( n − 1 ) < k y*(n-1)<k y∗(n−1)<k:
怪兽一定只能在 n n n轮死亡。
若 n n n是奇数,就是 a a a是最后一击。
若 n n n是偶数,就是 b b b是最后一击。
代码:
csharp
#include<bits/stdc++.h>
using namespace std;
typedef __int128 i128;
typedef long long ll;
typedef double db;
const db PI = acos(-1);
typedef array<ll, 2> PII; // vector<PII> a(n + 1);
const ll inf = 2e18 + 10;
const int mod = 998244353;
const int maxn = 2e5 + 10;
bool multi = 1;
void Solve() {
ll k, x, y; cin >> k >> x >> y;
ll xx = (k + x - 1) / x;
ll yy = (k + y - 1) / y;
if(xx == yy) {
if(xx % 2 == 1) {
cout << "Yes\nNo\n";
} else {
cout << "No\nYes\n";
}
} else {
cout << "Yes\nYes\n";
}
}
signed main() {
// freopen("test.in","r",stdin);
// freopen("code.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
ll T = 1;
if(multi) cin >> T;
while(T -- ) {
Solve();
}
return 0;
}
1003.黑洞合并
题意:
有 n n n个黑洞,每个黑洞有起始质量。
发生 n − 1 n-1 n−1次合并,每次合并后质量为 a i + a j a_i+a_j ai+aj
释放能量为 a i ∗ a j ( a i + a j ) a_i*a_j(a_i+a_j) ai∗aj(ai+aj)
问 n − 1 n-1 n−1次合并后释放能量之和的期望。取模
题解:
随便写一下,观察,无论谁先谁后合并,最后答案都是一样的,按循序计算一下就行。
代码:
csharp
#include <bits/stdc++.h>
#define int long long
#define PII pair<int,int>
using namespace std;
const int N =2e6+6;
const int mod=998244353;
int a[N],b[N];
int cnt[N];
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)cnt[i]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int ans=0;
for(int i=1;i<n;i++){
ans=(ans+a[i]*a[n]%mod*(a[i]+a[n])%mod )%mod;
a[n]=(a[i]+a[n])%mod;
}
cout<<ans<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
1006.融合矿石
题意:
有 n n n种矿石,质量为 a i a_i ai,含矿石的质量为 b i b_i bi.矿石都是无限的。
可以进行矿石融合,融合后的质量为 a i + a j a_i+a_j ai+aj,含矿石的质量为 b i + b j b_i+b_j bi+bj。
每种矿石的价值是 V b a V_{\frac{b}{a}} Vab,价值体系有10种。
背包有m的容量,问最多能装的最大价值是多少。
题解:
因为背包的大小为 m m m,那就能装质量为 1 1 1~ m m m的矿石,我们使 f [ i ] f[i] f[i]表示质量为 i i i的矿石,含矿质量为最大的值。
d p [ i ] dp[i] dp[i]表示背包为i时价值最大值,就是跑一遍 m m m种矿石 ( f [ m ] ) (f[m]) (f[m]),背包为 m m m的完全背包。
代码:
csharp
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define rep(i, j, k) for(int i=j;i<=k;i++)
using namespace std;
const int N=3006;
const int mod=1e9+7;
int a[N],b[N],v[20];
int f[N],dp[N];
void solve()
{
int n,m;
rep(i,1,10){
cin>>v[i];
}
cin>>n>>m;
rep(i,1,n){
cin>>a[i]>>b[i];
}
rep(i,1,m){
f[i]=0;
dp[i]=0;
}
rep(i,1,n){
rep(j,a[i],m){
f[j]=max(f[j-a[i]]+b[i],f[j]);
}
}
rep(i,1,m){
if(f[i]){
int xx=i*v[(f[i]*10-1)/i+1];
rep(j,i,m){
dp[j]=max(dp[j],dp[j-i]+xx);
}
}
}
cout<<dp[m]<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}