2019爪哇之星程序设计编程赛(个人赛)

A题 礼尚往来

给出n,表示1~n人送的礼物,分配给这n个人,要求不能分配给送这份礼物的人,这主要是个错排公式,解说:错排公式
(n-1)*(dp[n-1] + dp[n-2])

#include <iostream>
const int mod = 1e9 + 7 ; 
using namespace std ; 
typedef long long ll ;
const int N = 105 ; 
ll a[N] ; 
int main(){
	int t ;
	cin >> t ;
	a[1] = 0 , a[2] = 1 ;
	for (int i = 3 ; i <= N ; ++ i)
		a[i] = (i-1)*(a[i-1] + a[i-2])%mod ;  
	while(t --){
		int n ; 
		cin >> n ; 
		cout << a[n] << endl ; 
	}
	return 0 ; 
} 
C 题 屌丝逆袭

题意:计算周围四个数的总和价值最大,同号相减异号相加,同时比较最大值的下标,最后输出即可。

#include <iostream>
#include <cstring>
using namespace std ; 
const int N = 25 ; 
int maze[N][N] ; 
int f[N][N] ;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}} ; 
int main(){
	int n , m ; 
	while(cin >> n >> m){
		if (n == 0 && m == 0)	break ;
		memset(f,0,sizeof(f)) ; 
		for (int i = 1 ; i <= n ; ++ i)
		for (int j = 1 ; j <= m ; ++ j)
			cin >> maze[i][j] ; 
		int a = 1 , b = 1 ; 	 	
		for (int i = 1 ; i <= n ; ++ i){
			for (int j = 1 ; j <= m ; ++ j){
				int flag ; 
				if (maze[i][j] < 0)		flag = 1  ;
				else	flag = -1 ; 
				for (int k = 0 ; k < 4 ; ++ k){
					int x = i+dir[k][0] , y = j+dir[k][1] ; 
					if (x>=1&&x<=n&&y>=1&&y<=m)
						f[i][j] += flag*maze[x][y] ; 	
				}
				if (f[a][b] < f[i][j])	
					a = i , b = j ; 
			}
		}
		cout << a << " " << b << " " << f[a][b] << endl ; 
	}
	return 0 ;
}
D题 口算训练

题意:给出n个数。和q个询问,每个询问包含l,r,d ,问在区间[l,r]中的数相乘之后的数是否是d的倍数。
题解:记录n个数中每个数的质因子出现的下标,然后d也分解质因子的下标,若个数和区间都符合就输出Yes否则输出No,详细看代码。

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std ; 
const int N = 1e5 + 5 ;
vector<int> g[N] ;
bool judge(int l , int r , int d){
	for (int i = 2 ; i*i <= d ; ++ i){	//这里i*i要<=x
		int cnt  = 0 ; 
		while(d % i == 0){
			++ cnt ; 
			d /= i ; 
		}
		if (cnt){
			int t = upper_bound(g[i].begin(),g[i].end(),r)-lower_bound(g[i].begin(),g[i].end(),l);
			if (t < cnt)	return false ; 
		}		
	}
	if (d > 1)	{
		int t=upper_bound(g[d].begin(),g[d].end(),r)-lower_bound(g[d].begin(),g[d].end(),l);
        if(t < 1) 	return false ; 
        else	return true ; 
	} 
	return true ; 
}
int main(){
	int t ; 
	scanf ("%d",&t) ;
	while(t --){
		int n , q ; 
		for (int i = 1 ; i <= N; ++ i)	g[i].clear() ; 
		scanf ("%d%d",&n,&q) ; 
		for (int i = 1 ; i <= n ; ++ i){
			int x ; 
			scanf ("%d",&x) ; 
			for (int j = 2 ; j*j <= x ; ++ j){	//这里j*j要<=x
				while(x%j == 0){
					g[j].push_back(i) ; 
					x /= j ;  
				} 
			}
			if (x > 1)	g[x].push_back(i) ; 
		}
		while(q --){
			int l , r , d ; 
			scanf ("%d%d%d",&l,&r,&d) ; 
			if (judge(l,r,d))	printf ("Yes\n") ;
			else	printf ("No\n") ; 
		}
	} 
	return 0 ; 
}
E题 子串查询

题意:给出一串长度为n的字符串,然后有q个询问,询问区间[l,r]之间最小的子串有多少个,因为a比aa还小,所以只要统计该区间最小的字符个数即可。

#include <cstdio>
#include <cstring>
using namespace std ; 
const int N = 1e5 + 5 ;
int cnt[N][26] ;  
char s[N] ; 
int main(){
	int t ; 
	scanf ("%d",&t) ; 
	for (int k = 1 ; k <= t ; ++ k){
		int n , q ; 
		scanf ("%d%d",&n,&q) ; 
		scanf ("%s",s) ; 
		memset(cnt,0,sizeof(cnt)) ; 
		cnt[0][s[0]-'A'] ++ ; 
		for (int i = 1 ; i < n ; ++ i){
			for (int j = 0 ; j < 26 ; ++ j){
				cnt[i][j] = cnt[i-1][j] ; 
			}
			++ cnt[i][s[i]-'A'] ; 
		}
		printf ("Case #%d:\n",k) ;
		while(q --){
			int l , r ; 
			scanf ("%d%d",&l,&r) ; 
			int ans = 0 ;
			-- l , -- r ; //因为下标是从0开始的
			for (int i = 0 ; i < 26 ; ++ i ){
				if (cnt[r][i] - cnt[l-1][i] != 0){
					ans = cnt[r][i] - cnt[l-1][i] ; //找到最小的字符串个数
					break ; 
				} 
			} 
			printf ("%d\n",ans) ; 
		}
	}
	return 0 ; 
} 
F题

找最小值,略。

H题

题意:电梯从0层开始,上一层需要6秒,下一层需要4秒,一个人出电梯门需要1秒。
将所有人要去的层数升序排列,然后每到一个新层数,就用新层数减去旧层数然后乘于6 再+1 , 若不是新层数就+1即可,最后用最高的层数乘于4(要返回0层)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std ;
const int N = 20 ; 
int a[N] ;  
int main(){
	int t ;
	cin >> t ; 
	while(t --){
		int n ; 
		cin >> n ; 
		memset(a,0,sizeof(a)) ; 
		for (int i = 1 ; i <= n ; ++ i){
			cin >> a[i] ;  
		}
		sort(a+1,a+n+1) ; 
		int sum = 6*a[1] + 6 ; 
		for (int i = 2 ; i <= n ; ++ i){
			if (a[i] != a[i-1]){
				sum += 6*(a[i]-a[i-1]) + 6 ; 
			}
			else	++ sum ; 
		}
		sum += a[n]*4 ;
		cout << sum << endl ; 
	}
	return 0 ; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值