A题 Strange Partition
仔细思考可以发现其实最大的策略就是每个都去向上整除,最小的策略就是先求和再向上整除,因为你一旦能够凑成倍数,那么对你来说是亏的。
代码
#include <ctime>
#include <cstdlib>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstdio>
#include<string>
#include<string.h>
#include<list>
#include<queue>
#include<sstream>
#include<vector>
#include <cassert> // assert
#include<set>
#include<map>
#include<deque>
#include<stack>
using namespace std;
#define debug(x) cout<<"###"<<x<<"###"<<endl;
const int INF=0x3f3f3f3f,mod=1e9,Maxn=1e6;
const double eps=1e-8;
typedef long long ll;
int main(){
int t;
cin>>t;
while(t--){
ll n;
ll x;
ll Min=0;
ll Max=0;
ll a;
scanf("%lld%lld",&n,&x);
for(int i=0;i<n;i++){
scanf("%lld",&a);
Min+=a;
Max+=(a+x-1)/x;
}
cout<<(Min+x-1)/x<<" "<<Max<<endl;
}
}
B题 Strange Partition
找规律
这道题想得有点慢了。最开始题目读错,写了一个错的代码。然后思路错了。差不多一个半小时才发现的规律。
你手写几组样例,因为机器人操作一次就相当于把那个数复制一次加到总和里面,模拟把每个数的最多操作次数写出来,最多操作次数就是x的多少次幂。你会发现这一组数的操作次数取决于最小的那个数的操作次数。最小的那个数的操作次数之后的数只能等于最小的那个数的操作次数,然后最小的操作次数之前的数只能比最小操作次数多一。
#include <ctime>
#include <cstdlib>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstdio>
#include<string>
#include<string.h>
#include<list>
#include<queue>
#include<sstream>
#include<vector>
#include <cassert> // assert
#include<set>
#include<map>
#include<deque>
#include<stack>
using namespace std;
#define debug(x) cout<<"###"<<x<<"###"<<endl;
const int INF=0x3f3f3f3f,mod=1e9,Maxn=1e5+5;
const double eps=1e-8;
typedef long long ll;
struct Node{
ll a;
int cnt;
}node[Maxn];
int main(){
int t;
cin>>t;
while(t--){
ll n,x;
cin>>n>>x;
ll sum=0;
for(int i=0;i<n;i++){
scanf("%lld",&node[i].a);
sum+=node[i].a;
int cnt=0;
ll temp=node[i].a;
while(temp%x==0){
cnt++;
temp/=x;
}
node[i].cnt=cnt;
}
int Min=INF;
for(int i=0;i<n;i++){
if(node[i].cnt<Min)Min=node[i].cnt;
}
bool flag=0;
for(int i=0;i<n;i++){
if(node[i].cnt==Min){
flag=1;
}
if(flag){
sum+=node[i].a*Min;
continue;
}
sum+=node[i].a*(Min+1);
}
cout<<sum<<endl;
}
}
C. Strange Birthday Party
&enps;&esnp;因为B题花了太长时间,(还是太菜了 T T)。C题只有最后半小时做,然后相当了一种贪心策略。
因为它给的礼物的价值是升序排列的。对每个人的k升序排列,然后k越大给钱给k就越亏。给最大的k安排最小的礼物给他,次大的k给次大的礼物给他,这样一直给下去。相当于两个指针在往中间走,因为这种策略中间肯定会相遇,只到可以给钱。因为对于k小的,优先给钱,把礼物留给指向大的c的k。
代码
#include <ctime>
#include <cstdlib>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstdio>
#include<string>
#include<string.h>
#include<list>
#include<queue>
#include<sstream>
#include<vector>
#include <cassert> // assert
#include<set>
#include<map>
#include<deque>
#include<stack>
using namespace std;
#define debug(x) cout<<"###"<<x<<"###"<<endl;
const int INF=0x3f3f3f3f,mod=1e9,Maxn=1e6;
const double eps=1e-8;
typedef long long ll;
ll c[Maxn];
ll k[Maxn];
int main(){
int t;
cin>>t;
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&k[i]);
}
for(int i=1;i<=m;i++){
scanf("%lld",&c[i]);
}
sort(k+1,k+1+n);
int cnt=1;
ll sum=0;
for(int i=n;i>0;--i){
if(cnt>=k[i]){
sum+=c[k[i]];
}
else
sum+=c[cnt];
cnt++;
}
cout<<sum<<endl;
}
return 0;
}
总的来说,B题开慢了,最后半个小时来A的C,还是太菜了,争取下次冲击4题。