Codeforces Round 256 (Div. 2)
A.A - Rewards (签到)
题意
三种A物品,三种B物品;
容器一次只能装五个A或者十个B不能同时装A和B
思路
水
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+9;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int a=0,b=0;
for(int i=1;i<=3;i++){
int aa;cin>>aa;
a+=aa;
}
for(int i=1;i<=3;i++){
int aa;cin>>aa;
b+=aa;
}
int n;cin>>n;
int num1=a/5+(a%5?1:0);
int num2=b/10+(b%10?1:0);
cout<<(num1+num2<=n?"YES":"NO");
return 0;
}
B - Suffix Structures (分类讨论)
题意
让你判断字符串A能否变成字符串B
如果字符串A能通过删去某些数变成B 输出巴拉巴拉
如果字符串A能通过对调某个数变成B 输出巴拉巴拉
如果字符串A同时需要上面两个操作才能变成B 输出巴拉巴拉
如果字符串A通过上面两个操作都不能变B 输出巴拉巴拉
思路
还有啥,直接模拟呗
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+9;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
string s,t;
int a[maxn];
int b[maxn];
bool find(){
int pos=0;
for(int i=0;i<t.size();i++){
bool ok=false;
int j;
for(j=pos;j<s.size();j++){
if(s[j]==t[i]){ok=true;break;}
}
if(!ok)return false;
else pos=j+1;
}
return true;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin>>s>>t;
int len1=s.size(),len2=t.size();
for(int i=0;i<len1;i++){
a[s[i]-'a']++;
}
for(int i=0;i<len2;i++){
b[t[i]-'a']++;
}
int flag=0;
for(int i=0;i<26;i++){
if(a[i]==b[i])continue;
if(a[i]<b[i])cout<<"need tree",exit(0);
else{
flag=1;
}
}
if(!flag){
puts("array");return 0;
}
if(flag){
if(find())
puts("automaton"),exit(0);
else{
puts("both");return 0;
}
}
return 0;
}
C - Painting Fence(分治)
题意
给出一排木板,木板的高度为A[i],宽度为1.
你手里有一个大小为1的刷子,你每次可以一次性刷一条不间断直线
问你最少刷几次可以把这一排木板刷完
思路
首先 假设如果我们全部横着刷
那么我们就需要最爱的木板高度+其他凸出来的次数
假设我们数着刷那么我们就需要刷木板的个数
所以我们就只要这两种情况取个优
再判断横着刷的时候 凸出来的需要另外考虑 这又是一个小问题,所以我们可以分治去做
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+9;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n;
ll a[maxn];
ll dfs(int s,int t){
if(s>t)return 0;
ll mi=inf,need=0;
for(int i=s;i<=t;i++){
mi=min(a[i],mi);
}
need+=mi;
for(int i=s;i<=t;i++)
a[i]-=mi;
int st=s;
for(int i=st;i<=t;i++)
if(i==t&&a[i])
need+=dfs(st,i),st=i+1;
else if(!a[i])
need+=dfs(st,i-1),st=i+1;
return min(1LL*(t-s+1LL),need);
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
cout<<dfs(1,n);
return 0;
}
D.D - Multiplication Table (二分)
题意
对于一个乘法表 求出第K大的数是多少
思路
我们发现对于一行或者一列他们的值都是递增的 所以满足二分的性质
于是我们二分答案;
可以求出每一行有多少个值小于这个答案
include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+9;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
ll n,m,k;cin>>n>>m>>k;
ll l=0,r=n*m,ans=-1;
while(l<=r){
ll mid=(l+r)/2;
ll sum=0;
for(int i=1;i<=n;i++)
sum+=min(m,(mid-1)/i);
if(sum<k){
l=mid+1;
ans=mid;
}
else
r=mid-1;
}
cout<<ans;
return 0;
}
E - Divisors (dfs)
题意
定义一个函数为F(a){a为一个数组}
F(a)的值为a的元素的所有因数依次排列
定义一个数组P[a]
P[i]的递推式为P[i]=P(X[i-1])
现在给你P[0]让你求出P[k];
思路
很明显这个P是递归的,而且只需要输出前1e5项,那么我们就直接暴力枚举因子就行
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
vector<ll>ve;
int len;
ll num;
void dfs(ll n,ll k){
if(num>=1e5)return;
if(k==0||n==1){
num++;
cout<<n<<" ";
return ;
}
for(ll i=0;i<ve.size()&&ve[i]<=n;i++)
if(n%ve[i]==0)dfs(ve[i],k-1);
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
ll x,k;
cin>>x>>k;
for(ll i=1;i*i<=x;i++){
if(x%i==0){
ve.push_back(i);
if(i*i!=x)ve.push_back(x/i);
}
}
sort(ve.begin(),ve.end());
len=ve.size();
dfs(x,k);
return 0;
}