2017 JUST Programming Contest 4.0

本文精选了算法竞赛中的多个题目并提供了详细的解题思路及代码实现,涉及区间和计算、数列推导、字符串处理、矩阵操作等核心算法,旨在帮助读者理解并掌握算法竞赛中的常见问题解决技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A

题意:求所有区间的&和

思路:我们统计二进制中每一位的贡献,很显然如果连续一段区间二进制中某一位都为1,那么这个区间的任何子区间都满足答案,所以我们直接统计满足条件的子区间个数即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e6 + 10;
const LL INF = 1e9 + 10;
int num[qq];
int n;

int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		scanf("%d", &n);
		for(int i = 1; i <= n; ++i) {
			scanf("%d", num + i);
		}
		LL ans = 0, f = -1;
		LL l, r, cnt;
		for(int i = 0; i < 23; ++i) {
			cnt = 0;
			f = -1;
			for(int j = 1; j <= n; ++j) {
				if(f == -1) {
					if(num[j] & (1 << i)) {
						l = j;
						f = 1;
					}
				} else {
					if(!((num[j] & (1 << i)))) {
						f = -1;
						r = j - 1;
						cnt += (r - l + 1) + (1 + r - l) * (r - l) / 2;
					}
				}
			}
			if(f != -1) {
				r = n;
				cnt += (r - l + 1) + (1 + r - l) * (r - l) / 2;
			}
			ans += cnt * (LL)(1 << i);
//			printf("%lld\n", cnt);
		}
		printf("%lld\n", ans);
	}
	return 0;
}


B

题意:ai = (a(i - 1) - i) % m,求整个数组a

思路:题意保证了至少一个不为-1,所以找个一个不为-1的,向前向后推一下即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 5e5 + 10;
const LL INF = 1e9 + 10;
int num[qq];
int n, m;

int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		scanf("%d%d", &n, &m);
		int id = -1;
		for(int i = 1; i <= n; ++i) {
			scanf("%d", num + i);
			if(num[i] != -1)	id = i;
		}
		for(int i = id + 1; i <= n; ++i) {
			if(num[i] == -1)	num[i] = (num[i - 1] + 1) % m;
		}
		for(int i = id - 1; i >= 1; --i) {
			if(num[i] == -1) {
				if(num[i + 1] == 0)	num[i] = m - 1;
				else	num[i] = num[i + 1] - 1;
			}
		}
		for(int i = 1; i <= n; ++i) {
			printf("%d%c", num[i], i == n ? '\n' : ' ');
		}
	}		
	return 0;
}


C

队友写的

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const LL INF = 1e9 + 10;
struct Node{
	int x,p;
}a[qq],b[qq];
int c[qq];
bool cmp(const Node &u,const Node &v) {
	if(u.x==v.x) return u.p<v.p;
	return u.x<v.x;
}
int Bin(int key,int r) {
	int l=0,ans=0;
	while(l<=r) {
		int m=(l+r)>>1;
		if(b[m].x==key) {
			while(b[m+1].x==key) m++;
			return m;
		}
		else if(b[m].x<key) {
			ans=m;
			l=m+1;
		}
		else r=m-1;
	}
	return ans;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--) {
		int n;
		scanf("%d",&n);
		for(int i=0;i<n;i++) {
			scanf("%d",&a[i].x);
			b[i].x=a[i].x;
			a[i].p=i;
			b[i].p=i;
		}
		sort(b,b+n,cmp);
		for(int i=0;i<n;i++) {
			int num1=MOD-a[i].x-1;
			int p1;
			if(b[0].x>num1) p1=-1;
			else p1=Bin(num1,n-1);
			int p2=n-1;
			if(b[p1].p==i) p1--;
			if(b[p2].p==i) p2--;
			if(p1<0) c[i]=(b[p2].x+a[i].x)%MOD;
			else c[i]=max((b[p1].x+a[i].x)%MOD,(b[p2].x+a[i].x)%MOD);
		}
		for(int i=0;i<n;i++) printf("%d%c",c[i],i==n-1?'\n':' ');
	}
	return 0;
}


D

题意:给出一个长度为n的字符串,然后q次询问,每次给你a b c,问你区间a b 内出现字符c的次数

思路:前缀维护一下讨论一下就行

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 5e5 + 10;
const LL INF = 1e9 + 10;
int num[qq][26], tot[26];
int n, m;
char st[qq];

int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		scanf("%d%d", &n, &m);
		scanf("%s", st);
		int len = strlen(st);
		mst(num[0], 0);
		mst(tot, 0);
		for(int i = 0; i < n; ++i) {
			if(i != 0) {
				for(int j = 0; j < 26; ++j) {
					num[i][j] = num[i - 1][j];
				}
			}
			num[i][st[i] - 'a']++;
			tot[st[i] - 'a']++;
		}
		char s[5];
		while(m--) {
			int a, b;	scanf("%d%d", &a, &b);
			scanf("%s", s);
			a--, b--;
			LL ans = 0;
			if(b - a + 1 < n) {
				a %= n, b %= n;
				if(a <= b) {
						if(a - 1 < 0) {
							ans += num[b][s[0] - 'a'];
						} else {
							ans += num[b][s[0] - 'a'] - num[a - 1][s[0] - 'a'];
						}
					} else {
						if(a - 1 < 0) {
							ans += num[n - 1][s[0] - 'a'] + num[b][s[0] - 'a'];
						} else {
							ans += num[n - 1][s[0] - 'a'] - num[a - 1][s[0] - 'a'] + num[b][s[0] - 'a'];
						}
					}
			} else {
				LL tmp = (b - a + 1) / n;
				if((b - a + 1) % n == 0) {
					ans = tmp * tot[s[0] - 'a'];
				} else {
					ans = tmp * tot[s[0] - 'a'];
					a %= n, b %= n;
	//				printf("QQQ %lld\n", ans);
					if(a <= b) {
						if(a - 1 < 0) {
							ans += num[b][s[0] - 'a'];
						} else {
							ans += num[b][s[0] - 'a'] - num[a - 1][s[0] - 'a'];
						}
					} else {
						if(a - 1 < 0) {
							ans += num[n - 1][s[0] - 'a'] + num[b][s[0] - 'a'];
						} else {
							ans += num[n - 1][s[0] - 'a'] - num[a - 1][s[0] - 'a'] + num[b][s[0] - 'a'];
						}
					}
//					ans = (LL)tmp * tot[s[0] - 'a'] + (LL)(num[n - 1][s[0] - 'a'] - num[a - 1][s[0] - 'a']) + (num[b][s[0] - 'a']);
				}
			}
			printf("%lld\n", ans);
		}
	}
	

G

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e6 + 10;
const LL INF = 1e9 + 10;
int num[qq];
int pre[qq], suf[qq];

int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		int n;	scanf("%d", &n);
		for(int i = 1; i <= n; ++i) {
			scanf("%d", num + i);
		}
		for(int i = 1; i <= n; ++i) {
			if(i == 1)	pre[i] = num[i];
			else	pre[i] = max(pre[i - 1], num[i]);
		}
		for(int i = n; i >= 1; --i) {
			if(i == n)	suf[i] = num[i];
			else	suf[i] = min(suf[i + 1], num[i]);
		}
		int cnt = 0;
		for(int i = 2; i < n; ++i) {
			if(pre[i - 1] <= num[i] && num[i] <= suf[i + 1]) {
				cnt++;
			}
		}
		printf("%d\n", cnt);
	}
	return 0;
}


H

题意:给出n*m的矩阵,问你能否将行数为1 n 列数为1 m的全部是1,每次可以交换两个位置的元素,求出最小交换次数,不可就输出-1

思路:很简单,判断一下1的个数即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 5e5 + 10;
const int INF = 1e9 + 10;
char st[105];

int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		int n, m;	scanf("%d%d", &n, &m);
		int cnt1, cnt2, cnt3, cnt4;
		cnt1 = cnt2 = cnt3 = cnt4 = 0;
		for(int i = 1; i <= n; ++i) {
			scanf("%s", st + 1);
			for(int x, j = 1; j <= m; ++j) {
				x = st[j] - '0';
				if(i == 1 || j == 1 || i == n || j == m) {
					if(x == 0)	cnt1++;
				} else {
					if(x == 1)	cnt2++;
				}
			}
		}
		if(cnt2 >= cnt1) {
			printf("%d\n", cnt1);
		} else {
			puts("-1");
		}
	}
	return 0;
}



I

很简单的dp

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 5e5 + 10;
const LL INF = 1e9 + 10;
int num[qq], pos[qq];
int dp[qq];

int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		int n;	scanf("%d", &n);
		for(int i = 1; i <= n; ++i) {
			scanf("%d", num + i);
		}
		mst(pos, -1);
		dp[1] = 0, pos[num[1]] = 1;
		for(int i = 2; i <= n; ++i) {
			dp[i] = dp[i - 1] + 1;
			if(pos[num[i]] != -1) {
				dp[i] = min(dp[i], dp[pos[num[i]]] + 1);
			}
			pos[num[i]] = i;
		}
		printf("%d\n", dp[n]);
	}	
	return 0;
}


J

队友写的

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const LL INF = 1e9 + 10;
LL a[qq];
int main(){
	int t;	scanf("%d", &t);
	while(t--) {
		int n;
		scanf("%d",&n);
		for(int i=0;i<n;i++) scanf("%lld",&a[i]);
		if(n==1) {
			printf("%lld\n",a[0]%MOD);
			continue;
		}
		LL sum=(a[0]+a[1]+a[0]*a[1]%MOD)%MOD;
		for(int i=2;i<n;i++) {
			sum=(sum*(a[i]+1)%MOD+a[i])%MOD;
		}
		printf("%lld\n",sum%MOD);
	}		
	return 0;
}



K

队友写的

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const LL INF = 1e9 + 10;
LL a[30],F[15];
char s[25];
void init() {
	F[0]=1LL;
	for(int i=1;i<12;i++) F[i]=F[i-1]*1LL*i;
}
int main(){
	init();
	int t;	scanf("%d", &t);
	while(t--) {
		mst(a,0);
		int n;
		scanf("%d%s",&n,s);
		for(int i=0;i<n;i++) a[s[i]-'a']++;
		int cnt=0;
		for(int i=0;i<26;i++) {
			if(a[i]&1) cnt++;
			a[i]/=2LL;
		}
		if((n&1)&&cnt!=1||!(n&1)&&cnt!=0) {
			printf("0\n");
			continue;
		}
		LL sum=F[(n>>1)];
		for(int i=0;i<26;i++) sum/=F[a[i]];
		printf("%lld\n",sum);
	}		
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值