A. Vanya and Cubes
思路:累加计算叠到每个高度至少需要多少方块,然后找最后一个满足的即可。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
#define INF 1000000000
int main(){
int n;
while(cin>>n){
int i;
int sum=0;
int ssum=0;
for(i=1;;i++){
sum+=i;
ssum+=sum;
if(ssum>n)break;
}
cout<<i-1<<endl;
}
return 0;
}
B. Vanya and Lanterns
思路:想都没想敲了个二分。。结果T了。。正解是先排序,然后算相邻两个灯距离/2和首尾灯到边界的最大值,直接输出最大值即可。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
#define INF 1000000000
double pos[1010];
int n;
double l;
int main(){
while(cin>>n>>l){
for(int i=0;i<n;i++){
cin>>pos[i];
}
sort(pos,pos+n);
double re=0;
for(int i=0;i<n;i++){
re=max(re,(pos[i+1]-pos[i])/2);
}
re=max(re,pos[0]);
re=max(re,l-pos[n-1]);
printf("%.10lf\n",re);
}
return 0;
}
C. Vanya and Exams
思路:贪心。优先写性价比最高的,注意不要溢出分数上限就行了。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
#define INF 1000000000
struct ex{
int a;
int b;
};
ex exs[100010];
bool cmp(ex a,ex b){
return a.b<b.b;
}
ll n,r,avg;
int main(){
while(cin>>n>>r>>avg){
ll sum=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&exs[i].a,&exs[i].b);
sum+=exs[i].a;
}
sort(exs+1,exs+1+n,cmp);
ll need=avg*n-sum;
if(need<=0){
cout<<0<<endl;
continue;
}
ll ans=0;
for(int i=1;i<=n;i++){
ll tmp=need;
need-=min(need,r-exs[i].a);
ans+=(tmp-need)*exs[i].b;
if(need==0)break;
}
cout<<ans<<endl;
}
return 0;
}
D. Vanya and Computer Game
思路:居然是判断谁补的刀。。先是算出了一个差不多打死的时刻,然后去模拟。。结果超时了。应该这样做,把两个人的攻击间隔改为y秒A一刀和x秒A一刀,攻击频率没有改变,整型好处理。。然后把他们同时A出第一刀的时刻(其实就是最小公倍数)前的所有攻击和是谁A的都按时间顺序存在数组里。这样他们同时出刀以后,出刀顺序还是那个序列。最后把血量取模,检查最后一刀是谁A的就行。
关于"Both"的判断,有两种情况,一是最后剩2滴血;同时出刀,二是最后剩一滴血,同时出刀。只要检查A死那刀的前后各一刀即可判断出来。
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
#define INF 1000000000
ll gcd(ll a,ll b){
return a%b==0?b:gcd(b,a%b);
}
pair<ll,bool> p[2000000];
int main(){
ll n,x,y;
while(cin>>n>>x>>y){
ll lcm=x*y/gcd(x,y);
int cnt=0;
for(ll i=x;i<=lcm;i+=x){
p[cnt].second=0;
p[cnt++].first=i;
}
for(ll i=y;i<=lcm;i+=y){
p[cnt].second=1;
p[cnt++].first=i;
}
sort(p,p+cnt);
for(int i=1;i<=n;i++){
ll a;
scanf("%I64d",&a);
a--;
a-=a/(x+y)*(x+y);
a%=cnt;
if(p[a].first==p[(a+1)%cnt].first&&p[a].second!=p[(a+1)%cnt].second){
printf("Both\n");
continue;
}
if(p[a].first==p[(a+cnt-1)%cnt].first&&p[a].second!=p[(a+cnt-1)%cnt].second){
printf("Both\n");
continue;
}
if(p[a].second==1){
printf("Vanya\n");
}else{
printf("Vova\n");
}
}
}
return 0;
}
E. Vanya and Field
思路:gcd(dx,n)=1和gcd(dy,n)=1告诉我们,按这个向量,可以循环取n个点。然后把所有的点分为n类就行了,具体是x=0,y=i时循环能取到的点,分到i类,i取0~n-1。我的分类方法是,求dx关于模n的逆元(其实总复杂度没有减小,暴力就可以),然后据此算出x增加1时,y的增量。然后打表算出第0类(x=0,y=0能循环到的点)在x取不同值时,y的取值,据此就可以给所有点分类了。最后就是统计哪类点最多,随便找一个该类的点输出即可。
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
#define INF 1000000000
int cnt[1000010];
int x[100010];
int y[100010];
int ExtendedEuclid(int f, int d, int *result) {
int x1, x2, x3, y1, y2, y3, t1, t2, t3, q;
x1 = y2 = 1;
x2 = y1 = 0;
x3 = (f >= d) ? f : d;
y3 = (f >= d) ? d : f;
while (1) {
if (y3 == 0) {
*result = x3;
return 0;
}
if (y3 == 1) {
*result = y2;
return 1;
}
q = x3 / y3;
t1 = x1 - q*y1;
t2 = x2 - q*y2;
t3 = x3 - q*y3;
x1 = y1;
x2 = y2;
x3 = y3;
y1 = t1;
y2 = t2;
y3 = t3;
}
}
int tab[1000010];
int main(){
int n,m,dx,dy;
while(cin>>n>>m>>dx>>dy){
memset(cnt,0,sizeof(cnt));
int _x;//x的逆元
ExtendedEuclid(dx,n,&_x);
_x+=n; _x%=n;
int _dy=((ll)dy*_x)%n;//x增加1时,y的增量
for(int i=1;i<n;i++){
tab[i]=tab[i-1]+_dy;
tab[i]%=n;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
cnt[(y[i]+n-tab[x[i]])%n]++;
}
int k=0;
int MAX=0;
for(int i=0;i<n;i++){
if(cnt[i]>MAX){
MAX=cnt[i];
k=i;
}
}
int ans;
for(int i=1;i<=m;i++){
if((y[i]+n-tab[x[i]])%n==k){
ans=i;
break;
}
}
cout<<x[ans]<<" "<<y[ans]<<endl;
}
return 0;
}