您的位置:首页 > 理论基础 > 计算机网络

2019 ICPC南昌邀请赛网络赛部分题解

2019-04-20 18:33 447 查看

A.

题目:https://nanti.jisuanke.com/t/38220

题意:求前5个因子和等于它本身的数(不算自身)

   线性筛

[code]#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 4e6 + 100;

int prime
, f
, fu
, tot;
bool is_prime
;

void init() {
memset(is_prime, true , sizeof(is_prime));
for (int i = 2; i < N; i++) {
if (is_prime[i]) {
prime[tot++] = i;
f[i] = 1 + i;
fu[i] = i;
}
for (int j = 0; j < tot && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = false;
if (i % prime[j] == 0) {
fu[i * prime[j]] = fu[i] * prime[j];
if (fu[i] == i) {
f[i * prime[j]] = f[i] + i * prime[j];
}else {
f[i * prime[j]] = f[i / fu[i]] * f[fu[i] * prime[j]];
}
break;
}else {
fu[i * prime[j]] = prime[j];
f[i * prime[j]] = f[i] * f[prime[j]];
}
}
if (f[i] == i * 2)
printf("%d\n", i);
}
}

int main() {
puts("6");
puts("28");
puts("496");
puts("8128");
puts("33550336");
return 0;
}

C.

题目:https://nanti.jisuanke.com/t/38222

题意:f(x)是斐波那契数的第x项,g(x)=f(f(x)),对于给定的n,将其表示成若干个g数的和,要求字典序最小,n<10^100000

矩阵快速幂求一下f(x),预处理前29项g(x)。

可以发现g(x)的增长速度非常快,其实在第29项就已经超出10^100000,由于后面的项差过大,所以方法基本唯一,所以就把贪心选一下,然后前几项在特判一下取个最小字典序就ok了。

[code]import java.io.*;
import java.math.*;
import java.util.*;
public class Main
{
static int maxn = 29;
static BigInteger []w = new BigInteger[maxn];
static int []v = new int[maxn];
public static BigInteger f(BigInteger n){
n = n.subtract(BigInteger.ONE);
BigInteger [][]a = new BigInteger[2][2];
BigInteger [][]b = new BigInteger[2][2];
BigInteger [][]c = new BigInteger[2][2];
for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) a[i][j] = BigInteger.ZERO;
a[0][0] = a[1][0] = a[0][1] = BigInteger.ONE;
for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) b[i][j] = BigInteger.ZERO;
for(int i = 0; i < 2; i++) b[i][i] = BigInteger.ONE;
while(n.compareTo(BigInteger.ZERO) > 0){
if(n.mod(new BigInteger("2")).equals(BigInteger.ONE)){
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
c[i][j] = BigInteger.ZERO;
for(int k = 0; k < 2; k++){
c[i][j] = c[i][j].add(b[i][k].multiply(a[k][j]));
}
}
}
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
b[i][j] = c[i][j];
}
}
}
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
c[i][j] = BigInteger.ZERO;
for(int k = 0; k < 2; k++){
c[i][j] = c[i][j].add(a[i][k].multiply(a[k][j]));
}
}
}
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
a[i][j] = c[i][j];
}
}
n = n.divide(new BigInteger("2"));
}
//System.out.println("len " + b[0][0].toString().length());
return b[0][0];
}
public static void main(String[] args)
{
Scanner cin = new Scanner (System.in);
for(int i = 1; i < maxn; i++){
w[i] = f(f(BigInteger.valueOf(i)));
}
// System.out.println(w[6] + " " + w[7]);
int T = cin.nextInt();
while(T > 0){
T--;
BigInteger n = cin.nextBigInteger();
int tot = 0;
for(int i = maxn - 1; i > 0; i--){
if(n.equals(new BigInteger("5")) && i >= 4){
v[tot++] = 4;
v[tot++] = 3;
v[tot++] = 2;
v[tot++] = 1;
n = BigInteger.ZERO;
break;
}
if(n.equals(new BigInteger("4")) && i >= 4){
v[tot++] = 4;
v[tot++] = 2;
v[tot++] = 1;
n = BigInteger.ZERO;
break;
}
if(n.equals(new BigInteger("3")) && i >= 3){
v[tot++] = 3;
v[tot++] = 2;
v[tot++] = 1;
n = BigInteger.ZERO;
break;
}
if(n.equals(new BigInteger("2")) && i >= 2){
v[tot++] = 2;
v[tot++] = 1;
n = BigInteger.ZERO;
break;
}
if(n.equals(new BigInteger("1")) && i >= 1){
v[tot++] = 1;
n = BigInteger.ZERO;
break;
}
if(n.compareTo(w[i]) >= 0){
v[tot++] = i;
n = n.subtract(w[i]);
}
}
if(!n.equals(BigInteger.ZERO)) System.out.println(-1);
else{
for(int i = tot - 1; i >= 0; i--) System.out.printf("%d%c", v[i], i == 0 ? '\n' : ' ');
}
}
cin.close();
}
}

D.

题目:https://nanti.jisuanke.com/t/38223

先将表达式表示成用最少火柴棍能表达的形式,然后在此基础上添加火柴棍。

先预处理出i位数添加j个火柴棍能够得到的最大值,然后背包一下就ok了。

举个例子

1+1+222

最简表示1-1-111,剩余11根棒子。

一共三项,1,-1,-111,然后dp[i][j]表示前i项加j根棒子的和的最大值,转移显然。

关键是预处理比较麻烦,见代码吧。

[code]#include <bits/stdc++.h>
#define my_max(a, b) ((a) > (b) ? (a) : (b))
#define my_min(a, b) ((a) < (b) ? (a) : (b))
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i, s, t) for(int i = (int)(s); i <= (int)(t); i++)
#define rev(i, t, s) for(int i = (int)(t); i >= (int)(s); i--)
#define lson rt << 1
#define rson rt << 1 | 1
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double lb;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::vector<int> VI;
typedef std::vector<ll> VL;
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree;
ll gcd(ll x, ll y){ return y % x == 0 ? x : gcd(y % x, x); }
template<class T>T my_abs(T a){ if(a < 0) a = -a; return a; }
inline ll read(){
ll ret = 0, sign = 1;
char c = getchar();
while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar();}
while(c >= '0' && c <= '9'){ ret = ret * 10 + c - '0'; c = getchar(); }
return ret * sign;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}

//void expand_stack_space(){
//    int size = 256 << 20; // 256MB
//    char *p = (char*)malloc(size) + size;
//    __asm__("movl %0, %%esp\n" :: "r"(p));
//}
const int maxn = 100 + 7;
const ll inf = 1e18;
ll dp[maxn][maxn * 10], sa[maxn];
ll a[maxn][maxn], b[maxn][maxn];
int n;
char str[maxn];
int count(char c){
if(c == '-' || c == '1') return 0;
if(c == '7' || c == '+') return 1;
if(c == '4') return 2;
if(c == '2' || c == '3' || c == '5') return 3;
if(c == '0' || c == '6' || c == '9') return 4;
if(c == '8') return 5;
}
char icount(int c){
if(c == 1) return '7';
if(c == 2) return '4';
if(c == 3) return '5';
if(c == 4) return '9';
if(c == 5) return '8';
}
void init(){
for(int i = 1; i <= 10; i++){
for(int j = 0; j <= 5 * i; j++){
int c = j;
string s = "";
for(int k = 1; k <= i; k++){
if(c >= count('9')) s += '9', c -= count('9');
else if(c >= count('7')) s += '7', c -= count('7');
else s += '1';
}
for(int k = i; k >= 1; k--){
if(c == 0) break;
c += count(s[k - 1]);
if(c >= count('8')) s[k - 1] = '8', c -= count('8');
else{
s[k - 1] = icount(c);
c = 0;
}
}
ll res = 0;
//cout<<"s " + s<<endl;
for(char ss : s) res = res * 10 + ss - '0';
a[i][j] = res;
b[i][j + 1] = res;
}
b[i][0] = -b[i][1];
}
}
int main(){
#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int T;
init();
scanf("%d", &T);
while(T--){
scanf("%d", &n);
scanf("%s", str);
int cnt = 0;
for(int i = 0; i < n; i++) cnt += count(str[i]);
int num = 0, tot = 0;
for(int i = 0; i < n; i++){
if(str[i] == '-' || str[i] == '+'){
sa[++tot] = num;
num = 0;
}
else num++;
}
//printf("cnt %d\n", cnt);
sa[++tot] = num;
for(int i = 0; i <= tot; i++) for(int j = 0; j <= cnt; j++) dp[i][j] = -inf;
//比赛时初始化写错了, 还过了。emmmm
dp[0][0] = 0;
for(int i = 1; i <= tot; i++){
int len = sa[i];
//printf("len %d\n", len);
if(i == 1){
for(int k = 0; k <= 5 * len; k++){
for(int j = cnt; j >= k; j--){
dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + a[len][k]);
}
}
}
else{
for(int k = 0; k <= 5 * len; k++){
for(int j = cnt; j >= k; j--){
dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + b[len][k]);
}
}
}
}
printf("%lld\n", dp[tot][cnt]);
}
return 0;
}

G.

题目:https://nanti.jisuanke.com/t/38226

题解:

[code]#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;

typedef unsigned int ll;

const int N = 1e7 + 10;

int prime
, phi
, tot;
ll f
, gg
, fu
, res
;
bool is_prime
;

void init() {
memset(is_prime, true, sizeof(is_prime));
for (ll i = 1; i < N; i++)
f[i] = f[i - 1] + 1;
for (ll i = 1; i < N; i++) {
gg[i] = gg[i - 1] + i;
f[i] = f[i] * gg[i];
}
for (ll i = 1; i < N; i++) {
gg[i] = gg[i - 1] + i * i;
f[i] = f[i] * gg[i];
}
phi[1] = gg[1] = fu[1] = 1;
for (int i = 2; i < N; i++) {
if (is_prime[i]) {
prime[tot++] = i;
fu[i] = i;
phi[i] = i - 1;
gg[i] = i - 2;
}
for (int j = 0; j < tot && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = false;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
fu[i * prime[j]] = fu[i] * prime[j];
if (fu[i] == i) {
gg[i * prime[j]] = phi[i * prime[j]] - phi[i];
}else {
gg[i * prime[j]] = gg[i / fu[i]] * gg[fu[i * prime[j]]];
}
break;
}else {
fu[i * prime[j]] = prime[j];
phi[i * prime[j]] = phi[i] * phi[prime[j]];
gg[i * prime[j]] = gg[i] * gg[prime[j]];
}
}
}
for (ll i = 1; i < N; i++) {
res[i] = i * i * i * gg[i] + res[i - 1];
}
}

int n;

void solve() {
ll ans = 0;
for (ll l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans += (res[r] - res[l - 1]) * f[n / l];
}
printf("%d\n", ans % (1 << 30));
}

int main() {
//freopen("0in.txt", "r", stdin);
init();
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
solve();
}
return 0;
}

H.

题目:https://nanti.jisuanke.com/t/38227

两端两种,中间三种。特判n=1。

[code]#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod = 1e9 + 7;

ll quick_mod(ll n,ll x)
{
ll res=1;
while(x)
{
if(x&1) res=res*n%mod;
n=n*n%mod;
x>>=1;
}
return res;
}

int main()
{
ll n;
cin>>n;
if(n==1) cout<<1<<endl;
else cout<<quick_mod(3,n-2)*4%mod<<endl;
return 0;
}

I.

题目:https://nanti.jisuanke.com/t/38228

题意:给一个长为n(n <= 500000)的数组a, 对每个区间,求区间和乘区间最小值的最大值

先用单调栈求出以a[i]为最小值能够延伸的左端点L[i]和右端点R[i],然后求前缀和,建立一颗线段树。对于每个位置i,求出[L[i] - 1,i]前缀和的最大值Maxl、最小值Minl和[i, R[i]]的最大值Maxr、最小值Minr。这样就可以查询到以a[i]为最小值的区间的和的最大值和最小值。然后枚举最小值a[i]即可。

[code]#include <bits/stdc++.h>
#define my_max(a, b) ((a) > (b) ? (a) : (b))
#define my_min(a, b) ((a) < (b) ? (a) : (b))
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i, s, t) for(int i = (int)(s); i <= (int)(t); i++)
#define rev(i, t, s) for(int i = (int)(t); i >= (int)(s); i--)
#define lson rt << 1
#define rson rt << 1 | 1
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double lb;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::vector<int> VI;
typedef std::vector<ll> VL;
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef tree<
20000
;int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree;
ll gcd(ll x, ll y){ return y % x == 0 ? x : gcd(y % x, x); }
template<class T>T my_abs(T a){ if(a < 0) a = -a; return a; }
inline ll read(){
ll ret = 0, sign = 1;
char c = getchar();
while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar();}
while(c >= '0' && c <= '9'){ ret = ret * 10 + c - '0'; c = getchar(); }
return ret * sign;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}

//void expand_stack_space(){
//    int size = 256 << 20; // 256MB
//    char *p = (char*)malloc(size) + size;
//    __asm__("movl %0, %%esp\n" :: "r"(p));
//}
const int maxn = 5e5 + 7;
const ll inf = 1e18;
int n;
struct SegmentTree{
ll Max[maxn << 2], Min[maxn << 2];
void init(ll *a){
build(1, 1, n, a);
}
void push_up(int rt){
Min[rt] = min(Min[lson], Min[rson]);
Max[rt] = max(Max[lson], Max[rson]);
}
void build(int rt, int l, int r, ll *a){
if(l == r){
Max[rt] = Min[rt] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(lson, l, mid, a);
build(rson, mid + 1, r, a);
push_up(rt);
}
ll queryMin(int ql, int qr, int rt = 1, int l = 1, int r = n){
if(ql == l && qr == r) return Min[rt];
int mid = (l + r) >> 1;
ll res = inf;
if(qr <= mid) res = queryMin(ql, qr, lson, l, mid);
else if(ql > mid) res = queryMin(ql, qr, rson, mid + 1, r);
else{
res = min(queryMin(ql, mid, lson, l, mid), queryMin(mid + 1, qr, rson, mid + 1, r));
}
return res;
}
ll queryMax(int ql, int qr, int rt = 1, int l = 1, int r = n){
if(ql == l && qr == r) return Max[rt];
int mid = (l + r) >> 1;
ll res = -inf;
if(qr <= mid) res = queryMax(ql, qr, lson, l, mid);
else if(ql > mid) res = queryMax(ql, qr, rson, mid + 1, r);
else{
res = max(queryMax(ql, mid, lson, l, mid), queryMax(mid + 1, qr, rson, mid + 1, r));
}
return res;
}
}pre;
ll presum[maxn], a[maxn];
int L[maxn], R[maxn], st[maxn], top;
int main(){
#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
scanf("%d", &n);
presum[1] = 0;
for(int i = 2; i <= n + 1; i++){
scanf("%lld", a + i);
presum[i] = presum[i - 1] + a[i];
}
top = 0;
for(int i = 2; i <= n + 1; i++){
while(top > 0 && a[st[top]] >= a[i]) top--;
if(top > 0) L[i] = st[top] + 1;
else L[i] = 1;
st[++top] = i;
}
top = 0;
for(int i = n + 1; i >= 2; i--){
while(top > 0 && a[st[top]] >= a[i]) top--;
if(top > 0) R[i] = st[top] - 1;
else R[i] = n + 1;
st[++top] = i;
}
n++;
pre.init(presum);
ll ans = -inf;
for(int i = 2; i <= n; i++){
int l = L[i], r = R[i];
l = max(l - 1, 1);
// printf("i %d L %d R %d\n", i, l, r);
ll Maxl = pre.queryMax(l, i), Minl = pre.queryMin(l, i);
ll Maxr = pre.queryMax(i, r), Minr = pre.queryMin(i, r);
ll ans1 = (Maxr - Minl) * a[i];
ll ans2 = (Minr - Maxl) * a[i];
//printf("Max %lld Min %lld\n", Maxr - Minl, Minr - Maxl);
// printf("ans1 %lld ans2 %lld\n", ans1, ans2);
ans1 = max(ans1, ans2); ans1 = max(ans1, a[i] * a[i]);
ans = max(ans, ans1);
}
printf("%lld\n", ans);
return 0;
}

 

J.

题目:https://nanti.jisuanke.com/t/38229

题意:给一棵n(n <= 100000)个结点的树,q(q <= 100000)次询问,询问u到v的路径上边权小于等于k的边的数量

主席树+LCA,dfs一次从根向下建主席树,每次查询结点到根的路径上边权小于等于k的数的数量,令cnt(u)为u到根的路径上边权小于等于k的数的数量,则答案ans = cnt(u) + cnt(v) - 2 * cnt(lca(u, v))。也可以离线用树状数组实现。

[code]#include <bits/stdc++.h>
#define my_max(a, b) ((a) > (b) ? (a) : (b))
#define my_min(a, b) ((a) < (b) ? (a) : (b))
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i, s, t) for(int i = (int)(s); i <= (int)(t); i++)
#define rev(i, t, s) for(int i = (int)(t); i >= (int)(s); i--)
#define lson rt << 1
#define rson rt << 1 | 1
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double lb;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::vector<int> VI;
typedef std::vector<ll> VL;
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree;
ll gcd(ll x, ll y){ return y % x == 0 ? x : gcd(y % x, x); }
template<class T>T my_abs(T a){ if(a < 0) a = -a; return a; }
inline ll read(){
ll ret = 0, sign = 1;
char c = getchar();
while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar();}
while(c >= '0' && c <= '9'){ ret = ret * 10 + c - '0'; c = getchar(); }
return ret * sign;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}

//void expand_stack_space(){
//    int size = 256 << 20; // 256MB
//    char *p = (char*)malloc(size) + size;
//    __asm__("movl %0, %%esp\n" :: "r"(p));
//}
const int maxn = 1e5 + 7;
int root[maxn], fa[maxn][20], cnt, dep[maxn];
int sum[maxn * 50];
vector<int> num;
vector<pii> G[maxn];
struct node{
int ls, rs;
}Tree[maxn * 50];
int find(int x){
return lower_bound(num.begin(), num.end(), x) - num.begin() + 1;
}
void insert(int old_k, int &new_k, int pos, int l, int r){
new_k = ++cnt;
Tree[new_k] = Tree[old_k];
sum[new_k] = sum[old_k];
sum[new_k]++;
if(l == r) return ;
int mid = (l + r) >> 1;
if(pos <= mid) insert(Tree[old_k].ls, Tree[new_k].ls, pos, l, mid);
else insert(Tree[old_k].rs, Tree[new_k].rs, pos, mid + 1, r);
}
int query(int rt, int l, int r, int ql, int qr){
if(l == ql && r == qr) return sum[rt];
int mid = (l + r) >> 1;
int res = 0;
if(qr <= mid) res += query(Tree[rt].ls, l, mid, ql, qr);
else if(ql > mid) res += query(Tree[rt].rs, mid + 1, r, ql, qr);
else{
res += query(Tree[rt].ls, l, mid, ql, mid);
res += query(Tree[rt].rs, mid + 1, r, mid + 1, qr);
}
return res;
}
void dfs(int u, int f){
fa[u][0] = f;
dep[u] = dep[f] + 1;
for(int i = 1; i <= 19; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for(pii &p : G[u]){
if(p.fi != f){
insert(root[u], root[p.fi], p.se, 1, sz(num));
dfs(p.fi, u);
}
}
}
int lca(int u, int v){
if(dep[u] > dep[v]) swap(u, v);
int k = dep[v] - dep[u];
for(int i = 0; i <= 19; i++){
if((k >> i) & 1) v = fa[v][i];
}
if(u == v) return u;
for(int i = 19; i >= 0; i--){
if(fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
int n, m, up[maxn], vp[maxn], wp[maxn];
int main(){
#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i++){
scanf("%d%d%d", up + i, vp + i, wp + i);
num.push_back(wp[i]);
}
sort(num.begin(), num.end());
num.erase(unique(num.begin(), num.end()), num.end());
for(int i = 1; i < n; i++){
wp[i] = find(wp[i]);
G[up[i]].push_back(pii(vp[i], wp[i]));
G[vp[i]].push_back(pii(up[i], wp[i]));
}
dfs(1, 0);
for(int i = 1; i <= m; i++){
int u, v, k;
scanf("%d%d%d", &u, &v, &k);
int LCA = lca(u, v);
k = upper_bound(num.begin(), num.end(), k) - num.begin() + 1;
k--;
k = min(k, sz(num));
if(k == 0) puts("0");
else{
int ucnt = query(root[u], 1, sz(num), 1, k);
int vcnt = query(root[v], 1, sz(num), 1, k);
int LCAcnt = query(root[LCA], 1, sz(num), 1, k);
int ans = ucnt + vcnt - 2 * LCAcnt;
printf("%d\n", ans);
}
}
return 0;
}

K.

题目:https://nanti.jisuanke.com/t/38230

枚举长度,对于每个数可以算贡献,也可以打表找规律,结果都是一样的,能够发现每个数是否选取是对于区间长度%4的循环。

[code]#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
int a[maxn];
int p[maxn][4];

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,l,r;
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
for(int j=0;j<4;j++) p[i][j]=p[i-1][j];
p[i][i%4]^=a[i];
}
int q;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&l,&r);
int len=(r-l+1)%4;
if(len==0) printf("0\n");
if(len==1) printf("%d\n",p[r][l%4]^p[l-1][l%4]);
if(len==2) printf("%d\n",p[r][l%4]^p[l-1][l%4]^p[r][(l+1)%4]^p[l-1][(l+1)%4]);
if(len==3) printf("%d\n",p[r][(l+1)%4]^p[l-1][(l+1)%4]);
}
}
return 0;
}

M.

题目:https://nanti.jisuanke.com/t/38232

题意:给一个主串S,询问n次,每次给出一个串Ti,问Ti是否为S的子序列。

用nxt[i][c]记录位置i后c第一次出现的位置。查询直接往后跳即可。

[code]#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 1e5 + 100;
const int M = 26;

int n, m, L;
int nex
[M];
char str
;

void init() {
memset(nex, 0x3f3f3f3f, sizeof(nex));
L = strlen(str);
for (int i = L - 1; i >= 0; i--) {
for (int j = 0; j < 26; j++) {
if (str[i] - 'a' == j) nex[i][j] = i;
else nex[i][j] = nex[i + 1][j];
}
}
}

int main() {
//freopen("0in.txt", "r", stdin);
scanf("%s", str);
init();
scanf("%d", &n);
while (n--) {
scanf("%s", str);
int len = strlen(str);
int p = -1;
for (int i = 0; i < len && p < L; i++) {
p = nex[p + 1][str[i] - 'a'];
}
if (p < L) puts("YES");
else puts("NO");
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: