2024杭电9

1007.小猫钓鱼

题意:
一共有 2 n 2n 2n张牌, 1 1 1~ n n n的牌各有两张。
给定shuishui 和 sha7dow每人手上有 n n n张牌。
两人轮流出一张牌,按循序依次放好。
当一人A出的手牌在之前就出现过,那A可以把两张相同牌之间(包括两张一样)的牌都收为手牌。并获得等同于拿走牌数量的分数。

shuishui 先手操作,两人都想赢,问谁最后能获胜,或者平局。

题解:
两人手上都是单牌,显然不论先手打出什么,后手都可以出同样的单牌,直到先手的手牌为空,后手必胜。

两人都有双数牌时,先手先出单牌,后手就可以直接吃掉,没有意义。
先手出双牌,另外一人会减少一个双牌,先手+3分。所以后手一定会先没有手牌。先手必胜

代码:

#include 
#define int long long
#define PII pair
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(n1)>=k
一定可以在 n − 1 n-1 n1轮怪兽死亡。两只宠物都可能是最后一击。

如果 y ∗ ( n − 1 ) < k y*(n-1)y(n1)<k
怪兽一定只能在 n n n轮死亡。
n n n是奇数,就是 a a a是最后一击。
n n n是偶数,就是 b b b是最后一击。

代码:

#include
using namespace std;
typedef __int128 i128;
typedef long long ll;
typedef double db;

const db PI = acos(-1);
typedef array<ll, 2> PII; // vector 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 n1次合并,每次合并后质量为 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) aiaj(ai+aj)
n − 1 n-1 n1次合并后释放能量之和的期望。取模

题解:
随便写一下,观察,无论谁先谁后合并,最后答案都是一样的,按循序计算一下就行。

代码:

#include 
#define int long long
#define PII pair
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的完全背包。

代码:

#include
#define int long long
#define PII pair
#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;
}

你可能感兴趣的:(算法,c++,开发语言)