1- noip模拟赛 DAY1

本文解析了三项算法挑战赛题目,包括构建满足特定条件的数列、找出矩阵中出现奇数次的元素以及处理一系列模运算查询。每项挑战都提供了完整的代码实现。

T1 QAQ

为了方便,我们将字符串的下标从0开始计。那么我们要找的一组答案要满足:将这些答案中的数转成m进制数后,0..m-1中每一个数都能在某个数的某个数位上找到。这是充分必要的。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
ll kc[1010];
ll k,c,m,ans;
int main(){
    cin>>k>>c>>m;
    c --;
    if(k>m*(c+1)){
        printf("IMPOSSIBLE\n");
        return 0;
    }
    kc[0] = 1;
    for(ll i = 1; i <= c+1; i ++) kc[i] = kc[i-1] * k;
    for(ll i = 1; i <= k; i ++){
        ans += ((ll)(i-1)*kc[c-((i-1)%(c+1))]);
        if((i)%(c+1) == 0) printf("%I64d ", ans+1), ans = 0;
    }
    if(ans) printf("%I64d", ans+1);
    return 0;
}

T2 矩阵

容易发现,在输入中出现了奇数次的数组成了答案。将这些数排序输出即可。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
int a1[200010];
using namespace std;
int main(){
	freopen("matrix.in", "r", stdin);
	freopen("matrix.out","w",stdout);
	int n;
	scanf("%d", &n);
	int num = ((2*n)-1)*n;
	for(int i = 1; i <= num; i ++)
		scanf("%d", &a1[i]);
	sort(a1+1, a1+1+num);
	int now = -1, it = 0;
	for(int i = 1; i <= num+1; i ++){
		if(now == a1[i]) it ^= 1;
		else{
			if(it == 1) printf("%d ", now);
			now = a1[i], it = 1;
		}
	}
	return 0;
}

T3 %%%

一个重要的性质是:一个数a对另一个数b取模,a要么不变(此时a<b),要么值至少减少一半(此时a>=b)。所以对于每个询问x,只需要找到数列中第一个比x大的数,取模变成y,然后在这之后找到第一个比y大的数,这样最多找O(log x)次,每次找可以用倍增。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int a1[100010];
int find(int l, int r, int val){
	r ++;
	while(l != r){
		int mid = (l+r) >> 1;
		if(a1[mid] > val) l = mid+1;
		else r = mid;
	}
	return l;
}
int main(){
	freopen("mod.in","r",stdin);
	freopen("mod.out","w",stdout);
	int n, m, q;
	scanf("%d%d", &n, &m);
	a1[0] = 0x7fffffff;
	for(int i = 1; i <= n; i ++){
		scanf("%d", &a1[i]);
		if(a1[i] > a1[i-1]) i --, n --;
	}
	for(int i = 1; i <= m; i ++){
		scanf("%d", &q);
		int now = 1;
		while(now <= n){
			now = find(now, n, q);
			if(now <= n) q %= a1[now];
		}
		printf("%d\n", q);
	}
	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值