May Challenge 2019 Division 2 水題講解

Reduce to One

這題其實蠻水的?ios

題意就是說:c++

給定一個 1~n 的序列,每次挑兩個數 x y 合併,合併值爲 \(x+y+xy\) ,而後求不斷合併最後剩下的一個的最大值git

隨便搞搞發現答案應該是不管怎麼合併都同樣的,因此從左到右合併就行了,加上是第一題,大概就是這個結論ui

因而前綴信息處理一下每次直接輸出就行了...spa

//by Judge
#include<bits/stdc++.h>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
using namespace std;
const int mod=1e9+7;
const int M=1e6+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int CCF=-1,Z;
inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
inline void print(int x,char chr='\n'){
    if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n; arr q,f;
inline int mul(Rg int x,Rg int y){return 1ll*x*y%mod;}
inline int inc(Rg int x,Rg int y){return (x+=y)>=mod?x-mod:x;}
int main(){ Rg int T=read();
    fp(i,1,T) q[i]=read(); n=*max_element(q+1,q+1+T);
    fp(i,1,n) f[i]=inc(inc(f[i-1],i),mul(i,f[i-1]));
    fp(i,1,T) print(f[q[i]]); return Ot(),0;
}

Matches

給出兩堆火柴,每次取某堆火柴的必定數,這個數字要能整除另外一堆火柴的個數,誰先取完某一堆的獲勝code

貌似是博弈論,看看這整除好像和 gcd 頗有關的樣子,因而發現先掌握主動權的人必勝(就是說輪到某人取的時候,某一堆火柴整除另外一堆火柴的個數大於 1 ,那麼這我的就能夠徹底控制局面了),而後加些特判就 ok 了,複雜度帶個 log 但常數真的小element

//by Judge
#include<cstdio>
#include<cstring>
#include<iostream>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define ll long long
using namespace std;
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline ll read(){ ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} ll n,m,ans;
#define swap(a,b) (a)^=(b)^=(a)^=(b)
int main(){
    fp(i,1,read()){ n=read(),m=read();
        if(n<m) swap(n,m); ans=1;
        if(n%m==0){
            puts("Ari");
            goto end;
        }
        while(n<m<<1) n-=m,swap(n,m),ans^=1;
        puts(ans?"Ari":"Rich");
        end:;
    } return 0;
}

Where to Build the Roads

給出 n 個二維點,你能夠放置 n-1 條斜率爲 1 或 -1 的直線,而後要讓全部點裏最近的直線距離中的最大值最小,並輸出這個最小值乘上根號 2 的值,即求
\[ans=\sqrt2Min(~~~ MAX_{i=1}^n(dis _ i )~~~ )\]get

而後咱們發現只要求出全部的兩個點之間的 \({||x1-x2| -|y1-y2|| \over 2} + Min(|x1-x2|,|y1-y2|)\) 的最小值博客

然鵝 \(n^2\) 枚舉就完蛋了,因而咱們發現只須要通過每一個點記錄下該點的兩條斜率爲 -1 和 1 的直線,而後全部斜率相同的直線排個序,求兩條相鄰直線 \(y_1=(±1)x_1+b_1,y_2=(±1)x_2+b_2\)\(|b_2-b_1|\)的最小差值就是答案了string

//by Judge
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
using namespace std;
const int M=1e4+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline bool cmin(int& a,int b){return a>b?a=b,1:0;}
inline int read(){ int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} int n,ans; arr x,y,a,b;
int main(){
    fp(i,1,read()){ n=read(),ans=1e9;
        fp(i,1,n) x[i]=read(),y[i]=read(),a[i]=y[i]-x[i],b[i]=x[i]+y[i];
        sort(a+1,a+1+n),sort(b+1,b+1+n);
        fp(i,2,n) cmin(ans,a[i]-a[i-1]),cmin(ans,b[i]-b[i-1]);
        printf("%.8lf\n",ans/2.0);
    } return 0;
}

關於其餘題目可能能夠看看博主博客園裏面有沒有寫

相關文章
相關標籤/搜索