Educational Codeforces Round 122 (Rated for Div. 2)
导语
涉及的知识点
思维,DP
链接:Educational Codeforces Round 122 (Rated for Div. 2)
题目
A Div. 7
题目大意:给出一个正整数n,每次操作可以改变一位上的数,现在要求操作的结果没有前导0并且可以被7整除,求出操作最少次数后得到的结果数
思路:虽然可以操作每一位,但其实只用操作最后一位即可,因为最后一位尝试所有数后必然有一个使得整个数是7的个数
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int maxn=2e5+5;
int t,n,num[4],cnt;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >>t;
while(t--) {
cin >>n;
cnt=3;
if(n%7==0)//特判初始就符合条件的
{
cout <<n<<endl;
continue;
}
while(n) {//按位拆分
num[cnt--]=n%10;
n/=10;
}
bool flag=0;
cnt++;
if(cnt==3) {//如果只有一位
cout <<"7\n";
continue;
}
for(int j=0; j<=9; j++) {//只需要尝试变动最后一位即可
int tmp=num[3],res=0;
num[3]=j;
for(int k=cnt;k<=3;k++)
{
int p=3-k,in=num[k];
while(p--)in*=10;
res+=in;
}
if(res%7==0) {
flag=1;
cout <<res<<endl;
break;
}
num[3]=tmp;
if(flag)break;
}
}
return 0;
}
B Minority
题目大意:给出一个01串,现在需要选择一个严格连续子串,对于这个子串,如果里面0多则去掉子串所有1,否则相反,这样的去掉一次0/1定义一次操作,现在求出只能进行一次操作的情况下能够去掉的最多个数是多少
思路:统计01个数,如果不等,直接输出小值即可(可以模拟一下,去掉首或者尾或者都不拿),如果相等,输出相等值-1即可
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t;
string s;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >>t;
while(t--) {
cin >>s;
int len=s.length(),z=0,o=0;
for(int i=0;i<len;i++)//统计个数
if(s[i]=='0')z++;
else o++;
cout <<(o==z?o-1:min(o,z))<<endl;//特判
}
return 0;
}
C Kill the Monster
题目大意:略
思路:直接判断互相需要几次才能消灭对方即可,同归于尽也算可行解
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t,hc,dc,hm,dm,k,w,a;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >>t;
while(t--) {
cin >>hc>>dc>>hm>>dm>>k>>w>>a;
if((hc+dm-1)/dm>=(hm+dc-1)/dc) {//判断初始是否合法
cout <<"YES\n";
continue;
}
bool flag=0;
for(int i=0; i<=k; i++) {
int hcc=hc,ddc=dc;
hcc+=(k-i)*a,ddc+=i*w;
if((hcc+dm-1)/dm<(hm+ddc-1)/ddc)//需要向上取整
continue;
else {
flag=1;
cout <<"YES\n";
break;
}
}
if(flag)continue;
cout <<"NO\n";
}
return 0;
}
/*
1 1
1 2
0 0 0
*/
D Make Them Equal
题目大意:给出一个长度为 n n n的序列 a a a,初始时序列每个值为1,现在进行下列操作:选择两个整数 i ( 1 ≤ i ≤ n ) , x ( x > 0 ) i(1\le i\le n),x(x>0) i(1≤i≤n),x(x>0), a i = a i + ⌊ a i x ⌋ a_i=a_i+⌊\frac{a_i}{x}⌋ ai=ai+⌊xai⌋,进行完所有的操作之后,如果 a i = b i a_i=b_i ai=bi,将获得 c i c_i ci的价值,现在能最多进行k次操作,询问能获得最大价值
思路:首先数据量给的有点大,看似吓人,其实用不到那么多次操作,对于 a i a_i ai来说,从1到1e3最少只需要12次操作,将 a i a_i ai到对应 b i b_i bi的次数作为花费,价值为 c i c_i ci,那么原题就转变为,背包容量为k,每件物品花费为转移次数,价值为 c i c_i ci的01背包问题,总操作次数是不会超过 1.2 × 1 0 4 1.2×10^4 1.2×104的,所以直接背包容量开这么大即可(而不是 1 0 6 10^6 106)
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e3+5;
int t,n,k,b[maxn],c[maxn],a[maxn],dp[maxn*10+2121];
int v[maxn]= {0,0,1,2,2,3,3,4,3,4,4,5,4,5,5,5,4,5,5,
5,5,5,6,6,5,6,6,6,6,7,6,6,5,6,6,6,6,6,6,7,6,7,6,7,7,7,7,7,
6,7,7,7,7,7,7,7,7,7,8,8,7,8,7,7,6,7,7,7,7,7,7,7,7,7,7,8,7,8,8,
8,7,8,8,8,7,7,8,8,8,8,8,8,8,8,8,8,7,8,8,8,8,8,8,8,8,8,8,9,8,8,
8,8,8,8,8,8,9,9,9,9,8,9,9,9,8,9,8,8,7,8,8,8,8,8,8,8,8,8,8,8,8,9,8
,9,8,9,8,9,8,8,9,9,8,8,9,9,9,9,9,9,8,9,9,9,9,9,9,9,8,9,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,9,10,9,9,9,10,9,9,9,10,9,10,9,9,9,10,10,10,
10,10,10,10,10,10,9,10,10,10,10,10,10,10,9,10,10,10,9,10,9,9,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,10,10,9,10,10,10,9,10,10,10,9,10,10,10,9,10,9,10,10,10,10,10,9,10,9,
9,10,10,10,10,10,10,10,10,10,10,10,10,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,10,
10,10,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,11,10,10,10,10,10,10,10,11,10,10,10,10,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,11,10,10,10,10,10,10,10,10,10,10,10,11,10,10,10,11,10,10,10,11,11,11,11,11,10,11,11,
11,10,11,10,11,10,11,11,11,10,11,10,10,10,11,11,11,10,10,10,11,10,11,10,10,10,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,
11,10,11,11,11,10,11,10,10,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,11,10,11,10,11,10,11,10,11,10,11,10,10,10,11,10,11,10,11,10,11,10,11,10,10,11,11,11,11,10,11,11,
11,11,11,11,11,10,11,11,11,11,11,11,11,10,10,11,11,11,11,11,11,10,11,11,11,10,10,11,11,11,11,11,11,11,11
,11,11,10,11,11,11,10,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,
11,11,11,11,10,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,11,11,11,11,12,12,11,11,11,12,11,
11,11,12,11,12,11,11,11,11,12,12,11,12,11,12,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,12,11,12,11,11,12,12,11,12,11,11,11,12,
11,12,11,11,11,11,11,12,11,11,11,12,11,12,11,11,12,12,11,12,11,11,11,12,12,12,11,12,11,12,11,11,12,12,12,12,
12,12,12,12,12,12,11,12,12,12,12,12,12,12,11,12,12,12,11,11,12,12,11,12,12,12,12,12,12,12,11,12,12,12,11,12,
11,11,11,12,12,12,12,12,12,12,11,12,11,12,11,11,12,12,11,12,12,12,11,12,11,12,11,11,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,
};//预处理的值
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >>t;
while(t--) {
cin >>n>>k;
int ans=0;
for(int i=1; i<=n; i++) {
cin >>b[i];
b[i]=v[b[i]];//直接替换成费用
ans+=b[i];
}
for(int i=1;i<=n;i++)cin >>c[i];
for(int i=0; i<=min(ans,k); i++)dp[i]=0;//初始化
for(int i=1; i<=n; i++)//空间压缩后的背包DP
for(int j=min(k,ans); j>=b[i]; j--)
dp[j]=max(dp[j],dp[j-b[i]]+c[i]);
cout <<dp[min(k,ans)]<<endl;
}
return 0;
}
参考文献
无