A. Ostap and Grasshopper
题意
在一维空间上,从标有’G’的位置每次向左或向右k单位问能否到达位置’T’,且中途不能停在’#’位置。
分析
暴力枚举每次能到达的位置。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k,g,t;
scanf("%d %d",&n,&k);
string s; cin>>s;
for(int i=0;i<n;i++)
if(s[i] == 'G') g = i;
else if(s[i] == 'T') t = i;
if(g > t) swap(g,t);
bool flag = 1;
while((g+=k) < t)
if(s[g] == '#') flag = 0;
if(g != t) flag = 0;
printf("%s",flag?"YES":"NO");
}
B. Urbanization
题意
有n个人,每人有 wealthi 的财富。问如何从中选出 、n1、n2 个人分别组成两个集合,使得两个集合中人的平均财富和最大。
分析
ans=Σn11wealths1_in1+Σn11wealths2_in2=n2×Σn11wealths1_i+n1×Σn21wealths2_in1×n2
根据公式显然:在保证 n1<n2 的情况下,取财富最多的 n1 个人作为第一个集合,取剩余人中财富最多的 n2 个人作为第二个集合
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
long long wlt[N];
bool cmp(int a,int b){ return a > b; }
int main(){
int n,n1,n2;
scanf("%d %d %d",&n,&n1,&n2);
if(n1 > n2) swap(n1,n2);
for(int i=1;i<=n;i++)
scanf("%d",&wlt[i]);
sort(wlt+1,wlt+n+1,cmp);
double ans = 0;
for(int i=1;i<=(n1+n2);i++)
wlt[i] += wlt[i-1];
ans = wlt[n1] * 1.0 / n1 + (wlt[n1+n2] - wlt[n1]) * 1.0 / n2;
printf("%.8lf\n",ans);
}
C. Tennis Championship
题意
n个人进行淘汰赛,在满足只有进行过比赛场数相同或差一场的两人才可安排进行比赛的条件下,进行比赛最多的人能进行几场。
分析
考虑该问题的逆命题:比赛最多的人进行k场最少需要有多少人。
显然,
- 1场需要2人——f(1) = 2,
- 2场需要3人——f(2) = 3,
- 3场需要5人——f(3) = 5。
- n场需要进行过n-1场比赛人与进行过n-2场比赛的人决胜——f(n) = f(n-1) +f(n-2);
#include<bits/stdc++.h>
using namespace std;
const long long inf = 1ll<< 62;
long long K[100] = {1,2};
void getFibo(){
for(int i=2;;i++){
K[i] = K[i-1] + K[i-2];
if(K[i] > inf) return;
}
}
void getAns(long long n){
int l = 1, r = 89, mid, fin;
while(l <= r){
mid = (l+r) >> 1;
if(K[mid] > n) r = mid - 1;
else l = mid + 1, fin = mid;
}
printf("%d\n",fin);
}
int main(){
getFibo();
long long n;
scanf("%I64d",&n);
getAns(n);
}
D. Taxes
题意
一个数n最少需要用多少个素数的和来表示。
分析
结论题。。。哥德巴赫猜想
详见 OESI A051034
#include<bits/stdc++.h>
using namespace std;
//-----------------Miller-Rabin测试------------------------//可用O(sqrt(n))的素数判断方法代替
long long pow_mod(long long a,long long i,long long mod) {
long long ans = 1;
while(i >= 1) {
if(i&1) (ans *= a) %= mod;
i >>= 1;
(a *= a) %= mod;
}
return ans;
}
bool test(int n,int a,int d) {
if(n == 2) return true;
if(n == a) return true;
if((n&1)==0) return false;
while(!(d&1)) d = d>>1;
int t = pow_mod(a,d,n);
while((d!=n-1) && (t!=1) && (t != n-1)) {
t = (long long)t * t % n;
d = d<<1;
}
return (t == n-1 || (d&1) == 1);
}
bool isPrime(int n) {
if(n<2) return false;
int a[] = {2,7,61};
for(int i=0;i<=2;i++)
if(!test(n,a[i],n-1)) return false;
return true;
}
//-----------------------------------------------------//
int main(){
int n;
scanf("%d",&n);
if(isPrime(n)) printf("1");
else if(n%2==0 || isPrime(n-2)) printf("2");
else printf("3");
}