SMU Summer 2024 Contest Round 8

Product

C - Product (atcoder.jp)

__int128的使用方法-CSDN博客

这个因为是累乘,而且乘法中最小的数是2,累乘的结果最大又是10的5次方,可以确定这个的数据范围其实很小。我们可以利用map在遍历到每一层时将可能的结果存到map里面,每一层就利用上一层的储存结果进行更新。注意最后的累乘结果可能会很大。会超过long long范围所以要用int128来进行存储。

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5+7;
const int mod=1e9+7;
const int inf=LLONG_MAX;
using i128=__int128;

__int128 read()
{
	//直接在函数里面实现读字符串操作更简洁
	__int128 res=0;//初始结果赋值0
	char scan[1005];
	scanf("%s",scan);
	for(int i=0;i<strlen(scan);i++)
		res*=10,res+=scan[i]-'0';//实现进位
	return res;//返回__int128类型
}

void print(__int128 num)
{//递归调用,实现从高位向低位输出
	if(num>9) 
		print(num/10);
	putchar(num%10+'0');
}

void sovle(){
	
	i128 n,x;
	n=read(),x=read();
	map<i128,i128>u;
	for(i128 i=0;i<n;i++){
		i128 l;
		l=read();
		map<i128,i128>v;
		for(i128 j=0;j<l;j++){
			i128 z;
			z=read();
			if(i==0){
				v[z]++;
			}else{
				for(auto&c:u){
					v[z*c.first]+=c.second;
				}
			}
		}
		u.clear();
		for(auto&c:v){
			u[c.first]=c.second;
		}
	}
	print(u[x]);
	cout<<endl;
}

signed main()
{	
	ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
	int t = 1;
	//cin>>t;
	while (t--){
		sovle();
	}
	
	return 0;
}

C - Dice Sum

C - Dice Sum (atcoder.jp)

动态规划,规定dp[i][j]是在前i个数中总和不大于j的方案数。那么我们可以对要确定的数进行动态规划处理。

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5+7;
const int mod=998244353;
const int inf=LLONG_MAX;
using i128=__int128;

int dp[55][2550];

void sovle(){
	int n,m,k;
	cin>>n>>m>>k;
	
	memset(dp,0,sizeof(dp));
	//代表选前i个数, 总和比j小的结果。
	dp[0][0]=1;
    //选0个数,总和为0的情况数是1。
	for(int i=0;i<n;i++){//遍历的是选数数量情况。
		for(int j=0;j<=k;j++){//遍历的是总和情况。
			for(int z=j+1;z<=min(j+m,k);z++){//对于当前结果之后的所有更大可能的结果。
				dp[i+1][z]+=dp[i][j];//我们都把他们的方案数进行累加。因为他们已经满足小与小的了,那就更满足小于大的。
				dp[i+1][z]%=mod;//方案数取模。
			}
		}
	}
	
	int sum=0;
	for(int i=0;i<=k;i++){
		sum+=dp[n][i];//对于选n个数,总和不大于k的情况。
		sum%=mod;
	}
	cout<<sum<<endl;
}

signed main()
{	
	ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
	int t = 1;
	//cin>>t;
	while (t--){
		sovle();
	}
	
	return 0;
}

C - Ubiquity

C - Ubiquity (atcoder.jp)

每个位置一共有10个选择,以为一定要包含0和9,所以我们可以倒着去想用所有的结果减去没有9出现的次数,再减去没有0出现的次数。这样会减去来两次0和9都不出现的次数。所以我么们要再加上。最后的结果就是10^{n}-9^{n}*2+8^{n} 这样算出的数会很大,所以我们要用快速幂在运算过程中就不断取模。

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5+7;
const int mod1=998244353;
const int inf=LLONG_MAX;
using i128=__int128;
const int mod2=1e9+7;

int qmi(int a,int b,int p){
	int res=1;
	for(;b;b/=2,a=1ll*a*a%p){
		if(b%2){
			res=1ll*res*a%p;
		}
	}
	return res;
}

void sovle(){
	int n;
	cin>>n;
	int ans=(((((qmi(10,n,mod2)+mod2)-qmi(9,n,mod2))%mod2+mod2)-qmi(9,n,mod2))%mod2)+qmi(8,n,mod2)%mod2;
	cout<<ans%mod2<<endl;
}

signed main()
{	
	ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
	int t = 1;
	//cin>>t;
	while (t--){
		sovle();
	}
	
	return 0;
}

Left Right Operation

这个题很多次都见过。边写边忘罢了。

我们可以改动序列的左段和右段。所有的数都变成题目给出的 l 和 r,那么我们可以先处理出左段以各个数作为结尾的最大可能结果,和右段以各个数作为结尾的最大可能结果。最后再去遍历以每个数作为分隔得情况,取这些情况的最大值。我们就这样吧。

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5+7;
const int mod=1e9+7;
const int inf=LLONG_MAX;
void sovle(){
	
	int n,l,r;
	cin>>n>>l>>r;
	
	vector<int>a(n+2);
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	vector<int>qian(n+2),hou(n+2);
	
	for(int i=1;i<=n;i++){
		qian[i]=min(qian[i-1]+a[i],l*i);
	}
	for(int i=n;i>=1;i--){
		hou[i]=min(hou[i+1]+a[i],r*(n-i+1));
	}
	int sum=inf;
	for(int i=0;i<=n;i++){
		sum=min(qian[i]+hou[i+1],sum);
	}
	cout<<sum<<endl;
}

signed main()
{	
	ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
	int t = 1;
	//cin>>t;
	while (t--){
		sovle();
	}
	
	return 0;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值