Product
这个因为是累乘,而且乘法中最小的数是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
动态规划,规定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
每个位置一共有10个选择,以为一定要包含0和9,所以我们可以倒着去想用所有的结果减去没有9出现的次数,再减去没有0出现的次数。这样会减去来两次0和9都不出现的次数。所以我么们要再加上。最后的结果就是 这样算出的数会很大,所以我们要用快速幂在运算过程中就不断取模。
#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;
}