Problem A PERFECT NUMBER PROBLEM

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

题解:打表

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int a[N];
char str;
struct node{};
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    //scanf("%d",&n);
    printf("6\n28\n496\n8128\n33550336\n");
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

Problem B Greedy HOUHOU

https://nanti.jisuanke.com/t/38221

Problem C Angry FFF Party

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了。
JAVA版本一

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();
    }
}

Problem D Match Stick Game

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

题解:

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

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

举个例子

1+1+222

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

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

关键是预处理比较麻烦。

#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;
}

Problem E Card Game

https://nanti.jisuanke.com/t/38224

Problem F Information Transmitting

https://nanti.jisuanke.com/t/A2254

Problem G tsy's number

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

题解:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
 
typedef unsigned int ll;
 
const int N = 1e7 + 10;
 
int prime[N], phi[N], tot;
ll f[N], gg[N], fu[N], res[N];
bool is_prime[N];
 
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;
}

Problem H Coloring Game

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

题解:快速幂+规律

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int a[N];
char str;
struct node{};

ll POW(ll a,ll b,ll c){
    ll res=1;
    ll base=a%c;
    while(b){
        if(b&1)res=(res*base)%c;
        base=(base*base)%c;
        b>>=1;
    }
    return res;
}
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    scanf("%d",&n);
    if(n==1){
        cout<<1<<endl;
        return 0;
    }
    cout<<(4*POW(3,n-2,MOD))%MOD<<endl;
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

Problem I Max answer

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

题意:求区间最小值×区间和的最大值。

题解:用单调栈维护以每个数为最小值能拓展到最左边和最右边。然后用线段树维护一个前缀和。

对于一个数如果是正数查询当前位置到最右端的前缀和最大值,然后查询最左端到当前点的最小值做减法。

对于一个数如果是负数查询正好和上述情况相反。

C++版本一

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define N 500005
const LL inf = 1e18;
 
int a[N],L[N],R[N];
LL sum[N];
stack<int>S;
struct node
{
    LL mmax,mmin;
}T[N*4];
 
void build(int rt,int l,int r)
{
    if(l==r)
    {
        T[rt].mmax=sum[l];
        T[rt].mmin=sum[l];
        return ;
    }
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
    T[rt].mmax=max(T[rt<<1].mmax,T[rt<<1|1].mmax);
    T[rt].mmin=min(T[rt<<1].mmin,T[rt<<1|1].mmin);
}
 
LL query_max(int rt,int l,int r,int ql,int qr)
{
    if(l>=ql && r<=qr)
    {
        return T[rt].mmax;
    }
    int m=(l+r)>>1;
    LL ans1=-inf,ans2=-inf;
    if(ql<=m) ans1=query_max(rt<<1,l,m,ql,qr);
    if(qr>m) ans2=query_max(rt<<1|1,m+1,r,ql,qr);
    return max(ans1,ans2);
}
 
LL query_min(int rt,int l,int r,int ql,int qr)
{
    if(l>=ql && r<=qr)
    {
        return T[rt].mmin;
    }
    int m=(l+r)>>1;
    LL ans1=inf,ans2=inf;
    if(ql<=m) ans1=query_min(rt<<1,l,m,ql,qr);
    if(qr>m) ans2=query_min(rt<<1|1,m+1,r,ql,qr);
    return min(ans1,ans2);
}
 
int main()
{
    int n;
    sca(n);
    sum[0]=0;
    for(int i=1;i<=n;i++)
    {
        sca(a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        while(!S.empty()&&a[S.top()]>=a[i])S.pop();
        if(S.size()==0)L[i]=0;
        else L[i]=S.top();
        S.push(i);
    }
    while(!S.empty())S.pop();
    for(int i=n;i>=1;i--)
    {
        while(!S.empty()&&a[S.top()]>=a[i])S.pop();
        if(S.size()==0)R[i]=n;
        else R[i]=S.top()-1;
        S.push(i);
    }
    build(1,0,n);
    LL ans=-inf;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>=0)
        {
            LL ans1=query_max(1,0,n,i,R[i]);
            LL ans2=query_min(1,0,n,L[i],i);
            ans=max(ans,a[i]*(ans1-ans2));
        }
        else
        {
            LL ans1=query_min(1,0,n,i,R[i]);
            LL ans2=query_max(1,0,n,L[i],i);
            ans=max(ans,a[i]*(ans1-ans2));
        }
    }
    cout<<ans<<endl;
}

Problem J Distance on the tree

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

题意:给你一棵树,每条边都有一个权值,m个询问,问你从x到y的路径上有多少条边的值<=w。

题解:LCA
一边dfs一边建树,每一个点的状态是从它父亲的状态转移过来的。那么两个点之间的所有可能就是一个点到他们的lca+另一个点到他们的lca。注意存边权的话,是要存在儿子节点上的。
 

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
int ls[maxn*40],rs[maxn*40],sum[maxn*40],rt[maxn*40];
int tot,a[maxn],b[maxn];
int n,m;
struct node
{
    int to,next,wei;
}e[maxn<<1];
int head[maxn],fa[maxn][25],cnt,dep[maxn];
void add(int x,int y,int z)
{
    e[cnt].to=y;
    e[cnt].next=head[x];
    e[cnt].wei=z;
    head[x]=cnt++;
}
void update(int l,int r,int &root,int last,int val)
{
    root=++tot;
    ls[root]=ls[last];
    rs[root]=rs[last];
    sum[root]=sum[last]+1;
    if(l==r)
        return ;
    int mid=l+r>>1;
    if(mid>=val)
        update(l,mid,ls[root],ls[last],val);
    else
        update(mid+1,r,rs[root],rs[last],val);
}
int query(int l,int r,int ql,int qr,int num)
{
    if(l==r)
        return sum[qr]-sum[ql];
    int mid=l+r>>1;
    if(num<=mid)
        return query(l,mid,ls[ql],ls[qr],num);
    else
    {
        int ans=sum[ls[qr]]-sum[ls[ql]];
        ans+=query(mid+1,r,rs[ql],rs[qr],num);
        return ans;
    }
}
int all;
void dfs(int son,int ffa,int val)
{
    dep[son]=dep[ffa]+1;
    fa[son][0]=ffa;
    if(son!=1)
        update(1,maxn,rt[son],rt[ffa],val);
    for(int i=head[son];~i;i=e[i].next)
    {
        int ne=e[i].to;
        if(ne==ffa)
            continue;
        dfs(ne,son,lower_bound(b+1,b+1+all,e[i].wei)-b);
    }
}
void deal(){
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];

}

int lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=20;i>=0;i--)
        if(dep[fa[x][i]]>=dep[y])
            x=fa[x][i];
    if(x==y)return x;
    for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    int x,y,z;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z),b[i]=z;
        add(x,y,z),add(y,x,z);
    }
    sort(b+1,b+n);
    all=unique(b+1,b+n)-(b+1);
    tot=0;
    dfs(1,1,0);
    deal();
    while(m--)
    {
        scanf("%d%d%d",&x,&y,&z);
        z=upper_bound(b+1,b+1+all,z)-b-1;
        if(z==0)
            printf("0\n");
        else
        {
            int l=lca(x,y),ans=0;
            if(x!=l)
                ans=query(1,maxn,rt[l],rt[x],z);
            if(y!=l)
                ans+=query(1,maxn,rt[l],rt[y],z);
            printf("%d\n",ans);
        }
    }
    return 0;
}

Problem K MORE XOR

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

题解:规律

C++版本一

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define INF 0x3f3f3f3f
#define FI first
#define SE second
#define MP make_pair
#define PI pair<int,int>
#define lson l,m,rt<<1,ls,rs
#define rson m+1,r,rt<<1|1,ls,rs
#define test printf("here!!!\n")
using namespace std;
const int mx=1e5+10;
int n,m,p,q;
int qz[4][4][mx];
int hz[4][4][mx];
int a[mx];
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        memset(qz,0,sizeof(qz));
        memset(hz,0,sizeof(hz));
        scanf("%d",&n);
        for (int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
        for (int i=1;i<=n;++i)
        {
            for (int j=0;j<4;++j)
            {
                int id=(i-1)%4;
                int hgf=(1+j)%4;
                if (id==j)
                {
                    qz[1][j][i]=qz[1][j][i-1]^a[i];
                }
                else qz[1][j][i]=qz[1][j][i-1];
                if (id==j||id==hgf)
                {
                    qz[2][j][i]=qz[2][j][i-1]^a[i];
                }
                else qz[2][j][i]=qz[2][j][i-1];
                if (id==hgf)
                {
                    qz[3][j][i]=qz[3][j][i-1]^a[i];
                }
                else qz[3][j][i]=qz[3][j][i-1];
            }
        }
        for (int i=n;i>=1;--i)
        {
            for (int j=0;j<4;++j)
            {
                int id=(i-1)%4;
                int hgf=(1+j)%4;
                if (id==j)
                {
                    hz[1][j][i]=hz[1][j][i+1]^a[i];
                }
                else hz[1][j][i]=hz[1][j][i+1];
                if (id==j||id==hgf)
                {
                    hz[2][j][i]=hz[2][j][i+1]^a[i];
                }
                else hz[2][j][i]=hz[2][j][i+1];
                if (id==hgf)
                {
                    hz[3][j][i]=hz[3][j][i+1]^a[i];
                }
                else hz[3][j][i]=hz[3][j][i+1];
            }
        }
        scanf("%d",&q);
        int l,r;
        for (int i=1;i<=q;++i)
        {
            scanf("%d%d",&l,&r);
            int dis=(r-l+1)%4;
            int cxk=(l-1)%4;
            if (dis!=0) printf("%d\n",qz[dis][cxk][n]^qz[dis][cxk][l-1]^hz[dis][cxk][r+1]);
            else printf("0\n");
        }
    }
}

C++版本二

题解:规律

打表代码:

    while(1){
        scanf("%d",&n);
        for(int l=1;l<=n;l++){
            for(int r=l;r<=n;r++){
                memset(vis,0,sizeof(vis));
                for(int l1=l;l1<=r;l1++){
                    for(int r1=l1;r1<=r;r1++){
                        for(int l2=l1;l2<=r1;l2++){
                            for(int r2=l2;r2<=r1;r2++){
                                for(int i=l2;i<=r2;i++){
                                    vis[i]=!vis[i];
                                }
                            }
                        }
                    }
                }
                cout<<l<<" "<<r<<endl;
                for(int i=1;i<=12;i++){
                    cout<<vis[i];
                }
                cout<<endl;
            }
        }
    }

1、可以发现当区间确定时,是否取用成一个固定的规律;

2、同长度的区间,取法相同;

3、对于一定的区间取法循环节长度为4,例如【1,9】循环节1000,整个区间取法100010001,并且区间长度循环节也为4,例如长度为1的区间和长度为5的区间取法循环节相同;

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int a[N];
int vis[N];
char str;
int qz[4][4][N];//第一维:取法,第二维:开始位置
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        memset(qz,0,sizeof(qz));
        for(int i=1;i<=n;i++){
            for(int j=0;j<4;j++){
                int pos=(i-1)%4;
                int dis=(j+1)%4;
                if(pos==j){
                    qz[1][j][i]=qz[1][j][i-1]^a[i];
                }else{
                    qz[1][j][i]=qz[1][j][i-1];
                }
                if(pos==j||dis==pos){
                    qz[2][j][i]=qz[2][j][i-1]^a[i];
                }else{
                    qz[2][j][i]=qz[2][j][i-1];
                }
                if(dis==pos){
                    qz[3][j][i]=qz[3][j][i-1]^a[i];
                }else{
                    qz[3][j][i]=qz[3][j][i-1];
                }
            }
        }
        scanf("%d",&m);
        while(m--){
            scanf("%d%d",&l,&r);
            int pos=(r-l+1)%4;
            int dis=(l-1)%4;
            int res=qz[pos][dis][r]^qz[pos][dis][l-1];
            cout<<res<<endl;
        }
    }

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

C++版本三

Problem L qiqi'tree

https://nanti.jisuanke.com/t/38231

Problem M Subsequence

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

题解:预处理+贪心

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
#define endl "\n"
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,p,l,r,u,v;
int ans,cnt,flag,temp,sum;
int a[N];
char str[N],s[N];
int pos[N][130];
struct node{};
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    cin>>str+1;
    scanf("%d",&n);
    int len=strlen(str+1);
    for(int i=0;i<128;i++){
        pos[len][i]=len+1;
    }
    for(int i=len-1;i>=0;i--){
        for(int j=0;j<128;j++){
            pos[i][j]=pos[i+1][j];
        }
        pos[i][str[i+1]]=i+1;
    }
    while(n--){
        scanf("%s",s);
        int l=strlen(s);
        int id=pos[0][s[0]];
        int r=0;
        while(id<=len&&r<l){
            r++;
            id=pos[id][s[r]];
        }
        //cout<<l<<" "<<r<<endl;
        cout<<((r==l)?"YES":"NO")<<endl;
    }
    //}

#ifdef DEBUG
	printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}