这场比赛是学长组织的,我们打了重现赛,除了我一个人外其他人都是组队打的,省赛队友一直在摆烂,有时间也不来比赛,我们还是正式队伍呢,伤心死了...
总结一下,一个人打5个小时还是比较累的,一个人思考,一个人改错,而且不跟别人交流自己的思维会慢慢的下来。
B:https://ac.nowcoder.com/acm/contest/57773/B
这题一开始想的做法是O(nm),我想着可能碰巧过,所以我就试了试,结果没过,然后就啥啥思路了,做别的签到题了,然后作完签到题之后就又开始做这道题目了,想到了一个前缀和的做法,不过开一个1e8的long long数组,爆了内存了,然后就没啥思路了.....
正确思路:二分查找:
已知O(nm)铁定会超时和n和m的范围,所以至少O(nlogm)或者O(mlogn)是能过的
这样就很好想到二分了
在输入完a数组之后,对a进行排序,统计a的前缀和
然后遍历b数组,查找第一个大于b[i]的位置x,(lower_bound()或者upper_bound()函数)x位置之前的格子数即为s[x-1],x之后的格子即为吧b[i]*(n-x+1)
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n,m;
int a[300005];
ll b[300005];
ll s[300005];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i];
}
scanf("%d",&m);
ll ans=0;
for(int i=1;i<=m;i++){
scanf("%lld",&b[i]);
int cnt=upper_bound(a+1,a+1+n,b[i])-a;
ans=ans+s[cnt-1]+(n-cnt+1)*b[i];
}
printf("%lld\n",ans);
return 0;
}
这题其实就是个模拟,一开始思路还是不是很清楚就开始做题了,
然后就出现各种情况;
其实情况就有一下几种:
1.一开始钱够能买精炼器并且能买发电站(电不够的情况下)
2.一开始钱不够用,买不了精炼器和发电站,在挖一段时间后才买的
3.挖完矿也不能买精炼器和发电站
4.钱够用但是d+D>E,并且e=0(比赛的时候就这一点没想到,然后就错了,真的很可惜啊)
这是我比赛时候写的,写的异常麻烦
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int t ;
double w,m,E,D,c0,d,c1,e;
double p;
int main(){
scanf("%d",&t);
while(t--){
cin>>w>>m>>E>>D>>c0>>d>>p>>c1>>e;
//w为总价值,m为现在有的钱
double ans=w+m;
if(m>=c0){
if(d+D<=E){
ans=max(ans,m-c0+w*(1+p/100));
}else{
if(e!=0){
if((D+d-E)/e==int((D+d-E)/e)){
int k=(D+d-E)/e;
if(k*c1<=m-c0){
ans=max(ans,m-c0-k*c1+w*(1+p/100));
}
}else{
int k=(D+d-E)/e+1;
if(k*c1<=m-c0){
ans=max(ans,m-c0-k*c1+w*(1+p/100));
}
}
}
}
}
int k=0;
if((D+d-E)/e==int((D+d-E)/e)&&e){
if(D+d-E>=0){
k=(D+d-E)/e;
}
}else{
if(D+d-E>=0&&e){
k=(D+d-E)/e+1;
}
}
if(w+m>=c0+k*c1&&(m<c0+k*c1||m<c0)){
if(d+D<=E){
ans=max(ans,(w-c0+m)*(1+p/100));
}else{
if(e!=0){
if((D+d-E)/e==int((D+d-E)/e)){
int k=(D+d-E)/e;
if(w+m>=c0+k*c1){
ans=max(ans,(w+m-c0-k*c1)*(1+p/100));
}
}else{
int k=(D+d-E)/e+1;
if(w+m>=c0+k*c1){
ans=max(ans,(w+m-c0-k*c1)*(1+p/100));
}
}
}
}
}
printf("%0.2lf\n",ans);
}
return 0;
}
补题:
比赛时候不知道ceil()函数,即求大于等于这个数的最小的数
floor()小于等于这个数的最大的数
round()四舍五入函数
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
double w,m,E,D,c0,d,p,c1,e;
int t;
int main(){
scanf("%d",&t);
while(t--){
cin>>w>>m>>E>>D>>c0>>d>>p>>c1>>e;
double ans1=w+m;
double nm=0;
double ans2=0;
if(e==0){
if(d+D<=E){
if(c0<=m){
ans2=m-c0+w*(1+p/100);
}else{
ans2=(m-c0+w)*(1+p/100);
}
}else{
ans2=m+w;
}
}else{
nm=max(0.0,ceil((D+d-E)/e))*c1+c0;
if(nm<=m){
ans2=(m-nm)+w*(1+p/100);
}else{
ans2=(m+w-nm)*(1+p/100);
}
}
printf("%.2lf\n",max(ans1,ans2));
}
return 0;
}
G:这题我一开始想到了背包问题,然后又想到了线性dp,想了想两种方法好像都不对,然后就想了别的思路,然后就想到了这题登录—专业IT笔试面试备考平台_牛客网,然后想着怎么样去凑1这个数字,然后我想到了4*14-5*11=1
然后我比赛的时候是脑子是真的不清晰啊,因为题意说答案a,b,c都要<=1e9,然后我想到了5* n大于1e9的情况,然后,我就使得5n<=1e9
然后多出的部分用45来凑,那时想的是真麻烦
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
ll n;
int a,b,c,A,B,C;
int main(){
scanf("%d",&n);
if(n*5>1e9){
for(int i=1;;i++){
if(5*(n-45*i)<=1e9){
A=5*(n-45*i);
c=4*(n-45*i);
b=i;
break;
}
}
}else{
A=5*n;//11
c=4*n;//14
}
printf("%d %d %d\n",a,b,c);// 11 . 45 .14
printf("%d %d %d\n",A,B,C);
return 0;
}
即使5n超出1e9,我们可以先将n%45,然后在求11和14的数量,因为1可以表示任何数字
!!!
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n;
int a,b,c,A,B,C;
int main(){
scanf("%d",&n);
b=n/45;
n=n%45;
c=4*n;
A=5*n;
printf("%d %d %d\n",a,b,c);
printf("%d %d %d\n",A,B,C);
return 0;
}
其实这题还是很简单的,然后就是自己想的不清晰,我发现我的老毛病,没想清楚就开始做题了,一开始我只想到了x==y的情况才会有过边界,然后有想了想,如果max(x,y)%min(x,y)==0的情况也会有过边界的情况,然后交了好几发都wa了,然后就想到了4,6这种情况,也会过边界,其实就是gcd(x,y)!=1的情况就会过边界
参考案例,很容易得出答案
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
ll x,y;
int t;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&x,&y);
printf("%d\n",x+y-(__gcd(x,y)));
}
return 0;
}