牛客OI赛制测试赛题解

题目链接:https://www.nowcoder.com/acm/contest/181#description

A.斐波那契

题目:
设f[i]表示斐波那契数论的第i项
f[1]=1,f[2] =1,f[i] = f[i - 1] + f[i - 2]
给定一个n

题解:

这道题相对来说挺简单的,打下表发现规律之后就可以AC了

ac代码:

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	string s;
	while(cin >> s){
		if((s[s.length()-1]-48)%2) printf("-1\n");
		else printf("1\n");
	}
	return 0;
} 

B.送分题

水题不讲了

C.序列

题意:

有一个长度为n的序列,现在对其进行q次查询,每次输入k。询问是否存在k段区间,所有区间的区间和相等且每个数都必须被某一个数包含。

题解:

求序列的总和sum,每次查询如果(sum%k==0)则枚举一遍序列看是否满足条件,若(sum%k!=0)则必然错误

ac代码:

#include<iostream>
#include<cstdio>
using namespace std;
long long arr[1000010];
int main(){
    int n, q;
    long long w, k;
    scanf("%d%d", &n, &q);
    arr[0] = 0;
    for(int i = 1; i <= n; i++){
        scanf("%lld", &w);
        arr[i]+=(arr[i-1]+w);
    }
    while(q--){
        scanf("%lld", &k);
		if(arr[n]%k==0){
        	bool book = true;
        	long long K = 0;
        	int s = 0;
        	for(int i = 1; i <= n; i++){
        		K+=arr[i]-arr[i-1];
        		if(K == arr[n]/k){
        			K = 0;
        			s++;
        		}
        		else if(K > arr[n]/k){
        			break;
        		}
        	}
            if(s==k) printf("Yes\n");
            else printf("No\n");
        }
        else{
            printf("No\n");
        }
    }
    return 0;
}

D.小叶的巡查

题意:

求所有城市中哪两个城市相距最远

题解:

其实看完就知道是一颗树找最长链,两遍DFS/BFS就过了。

ac代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int MaxN = 1e6+1;
bool book[MaxN];
int n, u, v, w, Max = 0, Idx = 0;
struct Kd{
    int idx, val;
    Kd(int _idx, int _val){
        idx = _idx;
        val = _val;
    }
};
vector<Kd> node[MaxN];
void dfs(int idx, int w){
    int lens = node[idx].size();
    for(int i = 0; i < lens; i++){
        if(!book[node[idx][i].idx]){
            book[node[idx][i].idx] = true;
            if(w+node[idx][i].val > Max){
                Max = w+node[idx][i].val;
                Idx = node[idx][i].idx;
            }
            dfs(node[idx][i].idx, w+node[idx][i].val);
            book[node[idx][i].idx] = false;
        }
    }
}
int val;
char C;
inline void SI(){
    while((C=getchar())&&(C>'9'||C<'0')){}
    val=0;
    do{
        val=(val<<1)+(val<<3)+C-'0';
        C=getchar();
    }while(C>='0'&&C<='9');
}
int main(){
         
    scanf("%d", &n);
    for(int i = 0; i < n-1; i++){
        SI();
        u=val;
        SI();
        v=val;
        SI();
        w=val;
        node[u].push_back(Kd(v, w));
        node[v].push_back(Kd(u, w));
    }
    book[1] = true;
    dfs(1, 0);
    memset(book, false, sizeof(book));
    book[Idx] = true;
    dfs(Idx, 0);
    printf("%d\n", Max*10+(Max*(Max+1))/2);
    return 0;
}

E.旅行青蛙

题意:

求青蛙最多能看多少个景点

题解:

裸的LIS,时间复杂度O(nlogn)

ac代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN = 500010;
int a[MAXN], b[MAXN];
int Search(int num, int low, int high){
	int mid;
	while(low <= high){
		mid  = (low+high)/2;
		if(num >= b[mid]) low = mid+1;
		else high = mid-1;
	}
	return low;
}
int DP(int n){
	int i, len, pos;
	b[1] = a[1];
	len = 1;
	for(int i = 2; i <= n; i++){
		if(a[i] >= b[len]){
			len = len+1;
			b[len] = a[i];
		}
		else{
			pos = Search(a[i], 1, len);
			b[pos] = a[i];
		}
	}
	return len;
}
int main(){
	int n;
	while(scanf("%d\n", &n)!=EOF){
		for(int i = 1; i <= n; i++){
			scanf("%d", &a[i]);
		}
		printf("%d\n", DP(n));
	}
	return 0;
} 

F.子序列

题意:

给出一个长度为n的序列,你需要计算出所有长度为k的子序列中,除最大最小数之外所有数的乘积相乘的结果

题解:

求一遍各个数在长度为所有k的序列中出现的总次数减去当他们为最小值或最大值的情况得出结果。

做法:

组合数+快速幂

预处理一遍组合数,对序列进行一次排序,每个数计算a[i]^(C(n-1, k-1)-C(n-i-1, k-1)-C(i,k-1)).得到结果。

注意:指数取模需了解欧拉降幂定理

ac代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MaxN = 1e3+5;
const int mod=1e9+7;
int dp[MaxN][MaxN];
void init()
{
    dp[0][0]=1;
    for(int i=1;i<MaxN;i++){
        for(int j=1;j<=i;j++){
            dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%(mod-1);
        }
    }
}
 
long long q_pow(long long x,long long n,long long m){
    if(n == 0)  return 1;
    long long res = q_pow(x * x % m,n/2,m);
    if(n & 1)   res = res * x % m;
    return res;
}
int main(){
    int T, n, k;
    init();
    long long arr[10000], ans = 1;
    while(~scanf("%d", &T)){
        while(T--){
            ans = 1;
            scanf("%d%d", &n, &k);
            for(int i = 0; i < n; i++){
                scanf("%lld", &arr[i]);
            }
            sort(arr, arr+n);
            for(int i = 1; i < n-1; i++){
                int f = 0;
                if(n-i >= k) f+=dp[n-i][k];
                if(i+1 >= k) f+=dp[i+1][k];
                ans=(ans*q_pow(arr[i], ((dp[n][k]-f)%(mod-1)+mod-1)%(mod-1), mod))%mod;
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值