题意:大法师蓝量上限为 n(即超过部分不计)并且起初满蓝(即 n),每秒可以花费 x 释放一次技能,每秒会自动回蓝 y 点,先用技能后结算回蓝,问 m 秒内能最多放几次技能
起初没读懂样例,实际上可能会出现中途蓝低于 x,但是可以等几秒后又可以使用技能的情况
思维:如果 y>=x
,相当于这个法师不耗蓝,那么无疑每秒都可以释放技能
如果 y<x
,说明每秒结束如果使用了技能会损失蓝量,可能中途会出现蓝量不足 CD 回蓝。如果硬模拟在第6测试点 TLE,仔细读题 x+y<n
,说明蓝根本就不可能到达上限,m 秒内回的蓝都可以用上,所以直接整体计算释放 (n+y*(m-1))/x
次。将两个情况综合取 min 就是答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include<bits/stdc++.h> using namespace std; typedef long long ll;
void solve(){ ll n,m,x,y; cin>>n>>m>>x>>y; ll tmp=(n+(m-1)*y)/x; cout<<min(m,tmp)<<endl; }
signed main() { ios::sync_with_stdio(false),cin.tie(0); ll t;cin>>t; while(t--){ solve(); } return 0; }
|
题意:给出一系列三维坐标上的点,找出距离源点最近的点并输出距离最近的点到源点的距离(保留三位小数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include<bits/stdc++.h> using namespace std; typedef long long ll;
int n;
signed main() { ios::sync_with_stdio(false),cin.tie(0); while(cin>>n){ double minn=3000; for(int i=1;i<=n;++i){ int x,y,z; cin>>x>>y>>z; double temp=sqrt(1.0*(pow(abs(x),2)+pow(abs(y),2)+pow(abs(z),2))); minn=min(minn,temp); } cout<<fixed<<setprecision(3)<<minn<<endl; } return 0; }
|
题意:你有一张能最多写 n 个字符的纸,m 个可能重复的单词,你需要挑选一些不重复的写到纸上,单词之间必须用空格分隔,问最多能写下几个不同的单词
思路:时间很宽松暴力就可以过,我采用了用 set 容器去重后用 vector 排序从小到大取字符写纸上
为什么不用 set 直接排序?这就涉及知识盲区了,set 容器是在插入元素的时候自动去重排序的,所以想要它按照你的要求排好序不能用 sort()
(会报错,具体原因和运算符重载有关),而是应该重载其内部排序的库的运算符。与其这样不如直接再用个 sort()
支持的静态容器 vector
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <bits/stdc++.h> using namespace std;
bool cmp(string x, string y) { return x.size()<y.size(); }
signed main(){ ios::sync_with_stdio(false),cin.tie(0); set<string> seta; vector<string> vec; int n,m; while(cin>>n>>m){ string ch; for(int i=1;i<=m;++i){ cin>>ch; seta.insert(ch); }
for(auto x:seta)vec.push_back(x); sort(vec.begin(),vec.end(),cmp);
int res=0; for(int i=0;i<vec.size();++i) { n-=vec[i].size(); if(n>=0)res++; else break; n--; } cout<<res<<endl; } return 0; }
|
题意: 0 到 9 每个数字有 ci 个,不要求全部用完,求能组成的不含前导 0 且能被 4 整除的最大整数
思路:先不讨论结果为一位数的情况。那么不难想到其实能否整除 4 最多和后两位有关,要想数尽可能的大那么就应该保证最后来两位能整除 4 的同时用到的数尽可能的小,这样高位的数可以选择更大的数。这样先把两位数的情况按照优先级高的打表,贪心选择合适的就可以了。对于结果为个位的情况,单独看看有没有 8 4 0,有其中一个就输出(注意判断顺序)。难点在于结尾为 00 的情况,它也可以整除 4,但是不能存入打表的容器所以要特判,其次光判断是否有 2 个 0 还不行,因为前面必须有其他的数否则就出现前导 0 情况了。具体实现看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include<bits/stdc++.h> using namespace std; typedef long long ll;
vector<int> vec={ 20,12,32,40,24,44,52,60,16,36,64,56,72,76,80,28,84,68,88,92,96 };
int a[10],b[10];
inline bool check(int x){ while(x){ int y=x%10; if(b[y]==0)return 0; else --b[y]; x/=10; } return 1; }
void solve(){ memset(a,0,sizeof a); for(int i=0;i<10;i++) cin>>a[i];
if(a[0]>0&&a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9]==0){ cout<<0<<endl; return ; }
int flag=0;int ret=0; for(auto x:vec){ for(int i=0;i<10;i++) b[i]=a[i];
if(a[0]>=2){ flag=2; b[0]-=2; break; }
if(check(x)==1){ flag=1;ret=x; break; } }
if(flag==1){ for(int i=10;i>=0;i--) while(b[i]){ cout<<i; b[i]--; } cout<<ret<<endl; } else if(flag==2){ for(int i=10;i>=0;i--) while(b[i]){ cout<<i; b[i]--; } cout<<"00"<<endl; } else{ if(a[8]>0)cout<<8<<endl; else if(a[4]>0)cout<<4<<endl; else if(a[0]>0)cout<<0<<endl; else cout<<-1<<endl; } }
signed main() { ios::sync_with_stdio(false),cin.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; }
|