haue_oj_题目总结(2)


前面的代码跳转点我

关于杭电部分题目的题解可以参考以为大佬:杭电部分题解(大多数英文题面)

真无语了正文太长了,只能再开一个了hhhh

图片描述

1418 Counting Stars

题目描述:
We define a k k k-star graph ( k ≥ 2 ) (k\ge 2) (k2) is a connected undirected graph with k + 1 k+1 k+1 nodes and k k k edges satisfies that all the k k k edges are connected to a common node (and it’s easy to show that this node is unique), and we call this node as the center of the star graph, and the other nodes are the leaves of the star graph.

Now you are given a simple undirected graph with n n n nodes and m m m edges.

Your task is to calculate how many k k k-star graphs are there in the given graph for all the integers k ∈ [ 2 , n − 1 ] k \in [2,n-1] k[2,n1] .

Specifically, the problem can be described as follows:

How many ways are there to choose a node c c c and a set of k k k nodes { l 1 , l 2 , … , l k } \{l_1,l_2,\dots,l_k\} {l1,l2,,lk} in the given graph, satisfies that there exists edges connected c c c and each l i l_i li for all i ∈ [ 1 , k ] i\in [1,k] i[1,k] in the given graph. Two star graphs are considered different if the center node c c c is different or the set of leaves { l 1 , l 2 , … , l k } \{l_1,l_2,\dots,l_k\} {l1,l2,,lk} is different.

Let c n t k cnt_k cntk represent the number of k k k-star graphs in the given graph module 1 0 9 + 7 10^9+7 109+7 .

You only need to print the bitwise XOR sum of all the c n t k cnt_k cntk (i.e. c n t 2 ⊕ c n t 3 ⊕ ⋯ ⊕ c n t n − 1 cnt_2\oplus cnt_3\oplus\cdots\oplus cnt_{n-1} cnt2cnt3cntn1 ,where ⊕ \oplus represents bitwise XOR).

输入:
The first line of the input contains an integer T   ( 1 ≤ T ≤ 5 ) T\ (1\le T\le 5) T (1T5), indicating the number of the test cases.

For each test case:

The first line contains two integers n , m   ( 3 ≤ n ≤ 1 0 6 , 1 ≤ m ≤ 1 0 6 ) n,m\ (3\le n\le 10^6, 1\le m\le 10^6) n,m (3n106,1m106), indicating the number of nodes and edges in the given graph.

Then the following m m m lines, each line contains two integers u , v   ( 1 ≤ u , v ≤ n , u ≠ v ) u,v\ (1\le u,v\le n, u\not =v) u,v (1u,vn,u=v) , indicating an edge in the given graph. It’s guaranteed that the graph is simple.

输出
For each test case: print one line contains a single integer, indicating the bitwise XOR sum of all the c n t k cnt_k cntk.

题解

在这里插入图片描述

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

inline int rd() {
  int x = 0;
  bool f = 0;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) f |= (c == '-');
  for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return f ? -x : x;
}

#define N 1000007
#define mod 1000000007

int fpow(int x, int t = mod - 2) {
	int res = 1;
	for (; t; t >>= 1, x = 1ll * x * x % mod)
		if (t & 1) res = 1ll * res * x % mod;
	return res;
}

int fac[N], ifac[N], deg[N], ans[N];

int C(int n, int m) {
	if (n < m) return 0;
	return 1ll * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}

void work() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; ++i) deg[i] = ans[i] = 0;
	for (int i = 1; i <= m; ++i) {
      	int x; cin >> x; ++deg[x];
      cin >> x; ++deg[x];
	}
	for (int i = 1; i <= n; ++i) 
		for (int j = 2; j <= deg[i]; ++j) 
			ans[j] = (ans[j] + C(deg[i], j)) % mod;
	int res = 0;
	for (int i = 2; i <= n; ++i) res ^= ans[i];
	printf("%d\n", res);
}

int main() {
  ios::sync_with_stdio(false);
  	cin.tie(0);
  	
	fac[0] = ifac[0] = 1;
	for (int i = 1; i < N; ++i) fac[i] = 1ll * fac[i - 1] * i % mod;
	ifac[N - 1] = fpow(fac[N - 1]);
	for (int i = N - 2; i; --i) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;

	int t; cin >> t;
	while (t--) work();
	return 0;
}

1419 Typhoon

题目描述:
A terrible typhoon is about to make landfall, and you decide to leave your home and seek refuge.

We can regard the problem as occurring on a two-dimensional plane. You have n n n alternative shelters, and you need to choose one to go to. Specifically, the i i i-th shelter is located at point ( X i , Y i ) (X_i, Y_i) (Xi,Yi) .

Now the meteorological station gives the predicted typhoon track, which consists of m m m forecast points ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x m , y m ) (x_1,y_1),(x_2,y_2),\dots,(x_m,y_m) (x1,y1),(x2,y2),,(xm,ym) , where ( x 1 , y 1 ) (x_1,y_1) (x1,y1) is the starting point and ( x m , y m ) (x_m,y_m) (xm,ym) is the ending point. According to the forecast, the center of the typhoon will moves along the segments between two adjacent points in turn.

In order to simplify the model, it is assumed that the influence range of typhoon is a circle with radius r r r and the radius will never change during the move. If a point will be within or just on the boundary of the typhoon’s influence range at a certain time, then we consider this point to be unsafe.

The radius of a typhoon is unpredictable. So you want to know, for each shelter, what is the minimum typhoon radius that still makes it unsafe

输入:
Please note that unlike other problems, there is only one test case input for this problem.

The first line contains two integers m , n   ( 2 ≤ m , n ≤ 1 0 4 ) m,n\ (2\le m,n\le 10^4) m,n (2m,n104), indicating the number of forecast points of the typhoon track and the number of shelters.

Then the following m m m lines, each line contains two integers x i , y i   ( ∣ x i ∣ , ∣ y i ∣ ≤ 1 0 9 ) x_i,y_i\ (|x_i|,|y_i|\le 10^9) xi,yi (xi,yi109), indicating the coordinates of the i i i-th forecast points of the typhoon track.

Then the following n n n lines, each line contains two integers X i , Y i   ( ∣ X i ∣ , ∣ Y i ∣ ≤ 1 0 9 ) X_i,Y_i\ (|X_i|,|Y_i|\le 10^9) Xi,Yi (Xi,Yi109), indicating the coordinates of the i i i-th shelter.

输出
Output n n n lines, the i i i-th line contains a single real number r i r_i ri , represents the answer for the i i i-th shelter.
All the real number you output should be rounded into 4 decimals.

题解
对于每个点,计算其到所有线段的距离取 min 即可,复杂度 O(nm) 。

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

typedef long long ll;
#define eps 1e-8
#define z(x) (abs((x)) <= eps) // is zero

struct P {
    ll x, y;
    P (ll x = 0, ll y = 0) : x(x), y(y) {}
    P operator + (const P &p) const {return {x + p.x, y + p.y};} 
    P operator - (const P &p) const {return {x - p.x, y - p.y};} 
    P operator - () const {return {-x, -y};}

    ll operator | (const P &p) const {return x * p.x + y * p.y;} // dot
    ll operator ^ (const P &p) const {return x * p.y - y * p.x;} // cross
    
    ll norm() const {return x * x + y * y;}
    double dis(const P &p) const {return sqrt(((*this) - p).norm());}
} zero;

double abs(const P &p) {return sqrt(p.norm());}

struct L {
    P p, v;
    L(const P &p = zero, const P &v = zero) : p(p), v(v) {}
    double dis(const P &a) const {return abs(v ^ (a - p)) / abs(v);} 
};

struct S {
    P a, b;
    double dis(const P &p) const {
        if (((p - a) | (b - a)) < -eps || ((p - b) | (a - b)) < -eps) 
            return min(abs(a - p), abs(b - p));
        return L{a, b - a}.dis(p);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int m, n;
    cin >> m >> n;
    --m;
    vector<S> seg(m);
    cin >> seg[0].a.x >> seg[0].a.y;
    for (int i = 0; i < m; ++i) {
        if (i != 0) seg[i].a = seg[i - 1].b;
        cin >> seg[i].b.x >> seg[i].b.y;
    }
    for (int i = 1; i <= n; ++i) {
        P nw; cin >> nw.x >> nw. y;
        double ans = 1e18;
        for (auto s : seg) ans = min(ans, s.dis(nw));
        printf("%.4lf\n", ans);
    }
    return 0;
}

1420 GCD Magic

题目描述:
Z is learning GCD theory and he finds a difficult problem:

∑ i = 1 n ∑ j = 1 n [ gcd ⁡ ( 2 i − 1 , 2 j − 1 ) ] K \sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(2^i-1,2^j-1)]^K i=1nj=1n[gcd(2i1,2j1)]K

He doesn’t know how to solve it, but he knows it’s easy for you. Please help him.

Since the answer can be very large, you only need to print the answer mod  998244353 \text{mod}\ 998244353 mod 998244353.

输入:
The first line contains one integer T   ( 1 ≤ T ≤ 12 ) T\ (1\le T\le 12) T (1T12) which represents the number of test cases.

For each test case: One line contains two integers n   ( 1 ≤ n ≤ 1 0 9 ) n\ (1\le n\le 10^9) n (1n109) and K   ( 0 ≤ K ≤ 10 ) K\ (0\le K\le 10) K (0K10).

输出
For each test case: Print one line containing one integer which represents the answer.

题解
在这里插入图片描述

#include<cmath>
#include<cstdio>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int maxs=1000001,maxk=10,MOD=998244353;

int te,K;LL n;
int u[maxs+5],p[maxs+5];bool pri[maxs+5];
int C[maxk+5][maxk+5],val[maxk+5];
int lim,G[maxs+5];
unordered_map<LL,int> f;
int ans;

inline int ADD(int x,int y) {return x+y>=MOD?x+y-MOD:x+y;}
inline int MUL(int x,int y) {return (LL)x*y%MOD;}
int Pow(int w,int b) {int s;for (s=1;b;b>>=1,w=MUL(w,w)) if (b&1) s=MUL(s,w);return s;}
void Make(){
	for (int i=0;i<=maxk;i++){
		C[i][0]=1;
		for (int j=1;j<=i;j++)
			C[i][j]=ADD(C[i-1][j-1],C[i-1][j]);
	}
	for (int i=1;i<=maxk;i++) val[i]=MUL(1<<i,Pow((1<<i)-1,MOD-2));
	u[1]=1;
	for (int i=2;i<=maxs;i++){
		if (!pri[i]) p[++p[0]]=i,u[i]=MOD-1;
		for (int j=1,t;j<=p[0] && (t=i*p[j])<=maxs;j++){
			pri[t]=true;
			if (i%p[j]) u[t]=(MOD-u[i])%MOD;
			else {u[t]=0;break;}
		}
	}
}
int SumF(LL n){
	int ans=MUL(K&1?MOD-1:1,n%MOD);
	int BA=Pow(2,n%(MOD-1)),pw=BA;
	for (int j=1;j<=K;j++){
		int now=MUL(C[K][j],K-j&1?MOD-1:1);
		now=MUL(now,MUL(val[j],ADD(pw,MOD-1)));
		ans=ADD(ans,now);
		pw=MUL(pw,BA);
	}
	return ans;
}
int Sum(LL n){
	if (n<=lim) return G[n];
	if (f.count(n)) return f[n];
	int ans=SumF(n);
	for (LL l=2,r;l<=n;l=r+1){
		r=n/(n/l);
		ans=ADD(ans,MOD-MUL(Sum(n/l),(r-l+1)%MOD));
	}
	return f[n]=ans;
}
int main(){
	Make();
	for (scanf("%d",&te);te;te--){
		scanf("%lld%d",&n,&K);
		lim=pow(n,2.0/3)+1;
		for (int i=1;i<=lim;i++) G[i]=0;
		for (int i=1,pw=2;i<=lim;i++,pw=MUL(pw,2)){
			int F=Pow(pw-1,K);
			for (int j=i,k=1;j<=lim;j+=i,k++)
				G[j]=ADD(G[j],MUL(u[k],F));
		}
		for (int i=1;i<=lim;i++) G[i]=ADD(G[i],G[i-1]);
		f.clear();ans=0;
		for (LL l=1,r;l<=n;l=r+1){
			r=n/(n/l);
			ans=ADD(ans,MUL(ADD(Sum(r),MOD-Sum(l-1)),MUL(n/l%MOD,n/l%MOD)));
		}
		printf("%d\n",ans);
	}
	return 0;
}

1421 Snake

题目描述:
There are n n n snakes indexed from 1 1 1 to n n n, each snake’s length is 1 1 1 at first.

There will be battles between the snakes, each battle can take place between any two alive snakes.

After each battle, the winner eat the loser, and merge their body. For instance, if snake 1 battles with snake 2 and win, it will eat snake 2 and become 1->2, otherwise it will be eaten and the other snake will become 2->1. For another example, if snake 3->2->7 battles with snake 5->6->4, the winner will become 3->2->7->5->6->4 or 5->6->4->3->2->7.

In addition, if a snake’s length is greater than k k k after a battle, it will become the king of the snakes!

A final state is defined by the set of alive snakes after battles. For instance, for n = 3 n=3 n=3, all possible final states are {1,2,3},{1->2,3},{1->3,2},{2->1,3},{2->3,1},{3->1,2},{3->2,1},{1->2->3},{1->3->2},{2->1->3},{2->3->1},{3->1->2},{3->2->1}.

Now you know after battles, there are m m m snakes alive and no king of the snake exist. Your task is to calculate the number of different possible final states modulo 998244353 998244353 998244353

输入:
The first line of the input contains an integer T   ( 1 ≤ T ≤ 200 ) T\ (1\le T\le 200) T (1T200), indicating the number of the test cases.

The next T T T lines, each line has three integers n , m , k   ( 1 ≤ m , k ≤ n ≤ 1 0 6 ) n, m, k\ (1\le m,k \le n \le 10^6) n,m,k (1m,kn106), indicating the number of snakes at first, the number of snakes after battles and the body length that need to be surpassed to become the king of the snake.

It’s guaranteed that ∑ n ≤ 1 0 8 \sum n\le 10^8 n108.

输出
T T T lines, each line has one interger, indicating the answer

题解
在这里插入图片描述

#include <bits/stdc++.h>
using i64 = int64_t;
using u32 = uint32_t;
using u64 = uint64_t;
const int N = 1 << 20;
const int P = 998244353;
struct mint {
    int x;
    constexpr mint(int x = 0) : x(x) {}
    mint operator-() const { return x > 0 ? P - x : 0; }
    mint operator+(mint o) const { return x + o.x < P ? x + o.x : x + o.x - P; }
    mint operator-(mint o) const { return x - o.x < 0 ? x - o.x + P : x - o.x; }
    mint operator*(mint o) const { return int(u64(x) * o.x % P); }
    mint &operator+=(mint o) { return *this = *this + o; }
    mint &operator-=(mint o) { return *this = *this - o; }
    mint &operator*=(mint o) { return *this = *this * o; }
    mint inv() const { return pow(P - 2); }
    mint cbrt() const { return pow((P + P - 1) / 3); }
    mint pow(auto k) const {
        mint a = x;
        mint b = 1;
        for (; k; k >>= 1) {
            if (k & 1)
                b *= a;
            a *= a;
        }
        return b;
    }
    mint sqrt() const {
        if (pow(P >> 1).x != 1) return 0;
        mint a = pow(60);
        mint b = pow(119);
        for (int k = 21; k >= 0; --k)
            if (b.pow(1 << k).x != 1) {
                a *= mint(3).pow(P >> (k + 2));
                b *= mint(3).pow(P >> (k + 1));
            }
        return std::min(a.x, P - a.x);
    }
};
mint w[N];
mint fac[N];
mint inv[N];
mint ivv[N];
void __attribute__((constructor)) init() {
    w[N / 2] = 1;
    mint g = mint(3).pow(P / N);
    for (int i = N / 2 + 1; i < N; ++i) w[i] = w[i - 1] * g;
    for (int i = N / 2 - 1; i > 0; --i) w[i] = w[i << 1];
    fac[0] = fac[1] = 1;
    inv[0] = inv[1] = 1;
    ivv[0] = ivv[1] = 1;
    for (int i = 2; i < N; ++i) fac[i] = fac[i - 1] * i;
    for (int i = 2; i < N; ++i) inv[i] = inv[P % i] * (P - P / i);
    for (int i = 2; i < N; ++i) ivv[i] = ivv[i - 1] * inv[i];
}

int main() {
#ifdef LOCAL
    auto flush = [&]() {};
    auto ii = [&]() {
        int x;
        std::cin >> x;
        return x;
    };
    auto oo = [&](auto x, char c = 10) {
        std::cout << x << c << std::flush;
    };
#else
    char bufI[1 << 19], *ptrI = bufI, *endI = bufI + sizeof(bufI);
    char bufO[1 << 19], *ptrO = bufO, *endO = bufO + sizeof(bufO);
    fread(bufI, 1, sizeof(bufI), stdin);
    auto load = [&]() {
        memcpy(bufI, ptrI, endI - ptrI);
        fread(endI - ptrI + bufI, 1, ptrI - bufI, stdin);
        ptrI = bufI;
    };
    auto flush = [&]() {
        fwrite(bufO, 1, ptrO - bufO, stdout);
        ptrO = bufO;
    };
    auto ii = [&]() {
        if (endI - ptrI < 32) load();
        int x{};
        int n{};
        for (; *ptrI < 48; ++ptrI) n = *ptrI == 45;
        for (; *ptrI > 47; ++ptrI) x = x * 10 + *ptrI - 48;
        return n ? -x : +x;
    };
    auto oo = [&](auto x, char c = 10) {
        if (endO - ptrO < 32) flush();
        if (x < 0) x = -x, *ptrO++ = '-';
        char buf[20];
        char *end = buf + 20;
        char *ptr = buf + 20;
        *--ptr = c;
        for (; x >= 10; x /= 10)
            *--ptr = char(48 + x % 10);
        *--ptr = char(48 + x);
        memcpy(ptrO, ptr, end - ptr);
        ptrO += end - ptr;
    };
#endif
    int T = ii();
    while(T--) {
        int n = ii();
        int m = ii();
        int k = ii();
        mint a[n];
        mint b[n];
        n -= m;
        mint tmp = 1;
        for (int i = 0; i * k <= n; ++i) {
            a[i * k] = tmp;
            tmp = -tmp * (m - i) * inv[i + 1];
        }
        tmp = 1;
        for (int i = 0; i <= n; ++i) {
            b[i] = tmp;
            tmp =  tmp * (m + i) * inv[i + 1];
        }
        mint ans = 0;
        for (int i = 0; i <= n; ++i) ans += a[i] * b[n - i];
        ans *= ivv[m] * fac[n + m];
        oo(ans.x);
    }
    flush();
}

1422 Tree

题目描述:
There is a rooted tree of n n n vertices with the root in vertex 1 1 1, each vertex has zero or one heavy child linked with a heavy edge, a set of maximal connected heavy edges form a heavy chain. A single vertex can also form a heavy chain, so each vertex belongs to exactly one heavy chain.

Now we want to build a search tree to maintain some information of the original tree. For each heavy chain with k k k vertices, we construct a segment tree of depth ⌈ log ⁡ 2 2 k ⌉ \lceil \log_22k \rceil log22k to maintain it, with each leaf of the segment tree indicating a vertex on the heavy chain, and the parent of the segment tree’s root is the parent of the top vertex of the heavy chian.

Note that in our variant of the segment tree, every leaves have the same depth.

For instance, this is a possible original tree, note that a double slash indicating a heavy edge.

                    1
                  // \
                  2   7
                //    \\
                3       8
              //        \\
              4           9
            // \
            5  10
           /
          6
There are $4$ heavy chain in this tree. They are:
1->2->3->4->5
6
7->8->9
10
This is the search tree of the previous origin tree, note that the double slash here has no special meaning, just make the search tree looks more beautiful.

                    o
                  // \\
                 o     o
               // \\   //
              o    o   o
             / \  / \ /
            1  2 3  4 5
            |       | |
            o      10 6
           / \
          o   o
         / \  /
        7   8 9
Given such a original tree, your task is to calculate the depth of the search tree. The depth of the root is $1$.

输入:
The first line of the input contains an integer T   ( 1 ≤ T ≤ 20 ) T\ (1\le T \le 20) T (1T20) , indicating the number of the test cases.

For each test case:

The first line of the input contains an interger n   ( 1 ≤ n ≤ 1 0 6 ) n\ (1\le n\le 10^6) n (1n106) , indicating the number of the vertices in the original tree.

The next lines has n n n integers, indicating the parent of each vertex. Note that 0 0 0 indicating don’t have a parent.

The next lines has n n n integers, indicating the heavy child of each vertex. Note that 0 0 0 indicating don’t have a heavy child.

It’s guaranteed that ∑ n ≤ 1 0 7 \sum n\le 10^7 n107.

输出
T T T lines, each line has one interger, indicating the answer.

题解
树形动态规划。把每个重链顶端所在的子树的答案求出来。
转移的时候,深度等于重链本身所形成的树的深度,加上重链沿伸出的子树的深度的最大值。

#include <bits/stdc++.h>
using i64 = int64_t;
using u32 = uint32_t;
using u64 = uint64_t;
const int N = 1 << 20;

int ch[N];
int dp[N];
int node[N];
int head[N];
int next[N];

void solve(int u, int w) {
    node[u] = 1;
    for (int v = head[u]; v; v = next[v]) {
        if (v == ch[u]) {
            solve(v, w);
            node[u] = node[v] + 2;
        } else {
            solve(v, v);
            dp[w] = std::max(dp[w], dp[v] + std::__lg(node[v]) + 1);
        }
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    auto ii = [&]() {
        int x;
        std::cin >> x;
        return x;
    };
    auto oo = [&](auto x, char c = 10) {
        std::cout << x << c << std::flush;
    };
    int T = ii();
    while(T--) {
        int n = ii();
        for (int i = 1; i <= n; ++i) {
            int f = ii();
            next[i] = head[f];
            head[f] = i;
        }
        for (int i = 1; i <= n; ++i) ch[i] = ii();
        solve(1, 1);
        oo(dp[1] + std::__lg(node[1]) + 1);
        for (int i = 0; i <= n; ++i) ch[i] = dp[i] = node[i] = head[i] = next[i] = 0;
    }
}

1423 Count

题目描述:
You are given three positive integers n n n, m m m, and k k k.

Your task is to calculate the total number of sequences A A A of length n n n that satisfy the following conditions:
1. All elements of A A A are integers from 1 1 1 to m m m(inclusive).

2. Let A i A_i Ai be the i i i-th element of sequence A A A. For all positive integers i i i not exceeding k k k, it is satisfied that A i = A n − k + i A_i = A_{n-k+i} Ai=Ank+i.

Calculate the total number of such sequences A A A that satisfy the conditions and output the result modulo 998244353.

输入:
The first line contains an integer T ( T ≤ 1000 ) T (T\leq 1000) TT1000, representing the number of test cases.

Each of the next T T T lines contains three integers n n n, m m m, and k ( 1 ≤ n , m , k ≤ 1 0 18 , k ≤ n ) k(1 \leq n,m,k \leq 10^{18} , k \leq n) k1n,m,k1018,kn, representing the parameters for one test case.

输出
For each test case, output an integer representing the answer.

#include <iostream>
#include <algorithm>


using namespace std;

using i64 = long long;

const int mod = 998244353;

int qpow(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = 1ll * res * a % mod;
        a = 1ll * a * a % mod;
        b >>= 1;
    }
    return res;
}

void solve() {
    i64 n, m, k;
    cin >> n >> m >> k;
    m %= mod;
    if (k == n) {
        cout << qpow(m, n % (mod - 1)) << '\n';
    } else {
        cout << qpow(m, (n - k) % (mod - 1)) << '\n';
    }
}


int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();    
    }
    return 0;
}


1424 Perfect square number

题目描述:
You have an array of n n n elements a 1 , a_1, a1, a 2 , a_2, a2, . . . ... ... , a n a_n an.

You have an operation that can modify the value of a certain position to any of the values in [ 1 , 300 ] [1,300] [1,300]. (You can only perform it once)

Find the maximum number of intervals that satisfy the interval sum is a Perfect square number

输入:
Each test contains multiple test cases. The first line contains the number of test cases T T T T ≤ 5 T \le 5 T5).
The description of the test cases follows.

The first line contains one integer n n n 1 ≤   n ≤ 300 1\le \ n \le 300 1 n300).

The second line contains n n n integers a 1 ,   a 2 ,   . . . ,   a n a_1, \ a_2, \ ..., \ a_n a1, a2, ..., an 1 ≤ a i ≤ 300 1\le a_i \le 300 1ai300).

输出
For each test case, output the maximum number.

#include <bits/stdc++.h>
using namespace std;
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define ll long long
#define mp make_pair 
const int N=2010;
const int M=400;
int n,a[N],cnt1[N],cnt2[N];
ll sum[N],f[N];
inline bool pd(int x)
{
    int y=sqrt(x);
    if (y*y==x) return 1;
    return 0;
}
void gg(int x,int y,int z)
{
    int now=sum[y]-sum[x-1];
    rep(i,-300,300) 
      if (pd(now+i)) f[M+i]+=z;
}
int solve()
{
    rep(i,1,n) sum[i]=sum[i-1]+a[i];
    int ans2=0;
    rep(i,1,n)
      rep(j,i,n)
        if (pd(sum[j]-sum[i-1])) ans2++;
    return ans2;
}
int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    while (T--)
    {
        memset(cnt1,0,sizeof(cnt1));
        memset(cnt2,0,sizeof(cnt2));
        memset(sum,0,sizeof(sum));
        memset(f,0,sizeof(f));
	    cin>>n;
	    rep(i,1,n) cin>>a[i];
	    rep(i,1,n) sum[i]=sum[i-1]+a[i];
	    rep(i,1,n)
	    {
	        rep(j,0,i-1)
	          if (pd(sum[i]-sum[j])) cnt1[i]++;
	        cnt1[i]+=cnt1[i-1];
	    }
	    dep(i,n,1)
	    {
	      rep(j,i,n)
	        if (pd(sum[j]-sum[i-1])) cnt2[i]++;
	      cnt2[i]+=cnt2[i+1];
	    }
	    ll ans=0;
	    rep(i,1,n)
	    {
	        rep(j,i,n) gg(i,j,1);
	        rep(j,1,i-1) gg(j,i-1,-1);
	        ll tt=0;
	        rep(j,1,300)
	          tt=max(tt,f[j-a[i]+M]);
	        ans=max(ans,cnt1[i-1]+cnt2[i+1]+tt);
	    }
	    cout<<ans<<endl;
    }
    return 0;
}

1425 Pair Sum and Perfect Square

题目描述:
A permutation of n n n elements is an array of n n n numbers from 1 1 1 to n n n such that each number occurs exactly one times in it.

Given a permutation p p p of n n n elements, there are Q Q Q queries to be made.

Each query provides two integers L L L and R ( 1 ≤ L ≤ R ≤ n ) R (1 ≤ L ≤ R ≤ n) R1LRn, asking how many pairs ( i , j ) (i, j) i,j satisfy L ≤ i < j ≤ R L \leq i < j \leq R Li<jR and p i + p j p_i + p_j pi+pj is a square number.

A square number is the product of some integer with itself. For example, 9 9 9 is a square number, since it can be written as 3 2 3^2 32.

输入:
he first line contains an integer T ( T ≤ 5 ) T (T\leq 5) TT5, representing the number of test cases.

For each test case, the input consists of Q + 3 Q+3 Q+3 lines:

The first line contains an integer n ( 1 ≤ n ≤ 1 0 5 ) n (1 \leq n \leq 10^5) n(1n105, representing the length of permutation p p p.

The second line contains n n n integers p 1 , p 2 , . . . , p n ( 1 ≤ p i ≤ n ) p_1, p_2, ..., p_n (1 \leq p_i \leq n) p1,p2,...,pn1pin, representing the elements of permutation p p p.

The third line contains an integer Q ( 1 ≤ Q ≤ 1 0 5 ) Q (1 \leq Q \leq 10^5) Q1Q105, indicating the number of queries.

The next Q Q Q lines each contain two integers L L L and R ( 1 ≤ L ≤ R ≤ n ) R (1 \leq L \leq R \leq n) R1LRn, representing the range of each query.

输出
For each query in each test case, output one line containing an integer, representing the answer.

#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <functional>
#include <cstring>

using namespace std;

const int N = 200010;

int p[N], pos[N];
int sq[N], m, n, k;

struct Fenwick {
  int tr[N];
  inline int lowbit(int x) {
    return x & -x;
  }
  inline void add(int x, int v) {
    for (; x <= n; x += lowbit(x))
      tr[x] += v;
  }
  inline int ask(int x) {
    int res = 0;
    for (; x; x -= lowbit(x))
      res += tr[x];
    return res;
  }
  void clear() {
    memset(tr, 0, sizeof tr);
  }
} t;

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  int T;
  cin >> T;
  while (T--) {
    t.clear();
    cin >> n;
    m = 0;
    for (int i = 1; i * i <= 2 * n - 1; i++) {
      sq[++m] = i * i;
    }
    for (int i = 1; i <= n; i++) {
      cin >> p[i];
      pos[p[i]] = i;
    }
    cin >> k;
    vector<vector<pair<int, int>>> q(n + 1);
    for (int i = 1; i <= k; i++) {
      int l, r;
      cin >> l >> r;
      q[r].emplace_back(i, l);
    }
    int tot = 0;
    vector<int> ans(k + 1);
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= m; j++) {
        if (sq[j] <= p[i]) continue;
        if (sq[j] - p[i] > n) break;
        if (pos[sq[j] - p[i]] < i) t.add(pos[sq[j] - p[i]], 1), ++tot;
      }
      for (auto [id, l] : q[i]) {
        ans[id] = tot - t.ask(l - 1);
      }
    }
    for (int i = 1; i <= k; i++) {
      cout << ans[i] << '\n';
    }
  }
  return 0;
}


1426 Calculate

题目描述:
Ming is on a map. There are n n n vertexes in the map. For each vertex, there is only one one-way edge that can reach another vertex on the map.

Ming has a number y y y in his hand, and when he reaches a certain vertex i i i, the number in his hand will change to y × k i + b i y\times k_i+b_i y×ki+bi.

There are several inquiries, each query Ming will start from a vertex x x x and walk l l l steps. At each step Ming starts from the current vertex and proceeds along the outgoing arc of that vertex to the next vertex. The initial number in his hand is y y y, and he wants to know what the number in his hand will become in the end.The answer is modulo 1 0 9 + 7 10^9+7 109+7

输入:
The first line, input a positive integer T ( 1 ≤ T ≤ 5 ) T(1\leq T\leq 5) T(1T5), representing the number of test data.

For each test, first line input a row of two positive integers n , q ( 1 < n , q ≤ 1 0 5 ) n,q(1< n,q\leq 10^5) n,q(1<n,q105), representing the number of points in the map and the number of queries.

The next line inputs n n n positive integers k i ( 1 ≤ k i ≤ 1 0 5 ) k_i(1\leq k_i\leq 10^5) ki(1ki105) representing the value of k k k on each vertex

The next line inputs n n n positive integers b i ( 1 ≤ b i ≤ 1 0 5 ) b_i(1\leq b_i\leq 10^5) bi(1bi105) representing the value of b b b on each vertex

The next line inputs n n n positive integers p i ( 1 ≤ p i ≤ n ) p_i(1\leq p_i\leq n) pi(1pin) represents the vertex reachable from vertex i i i, guaranteeing p i ≠ i p_i\neq i pi=i.

The next q q q lines,each line has three positive integers x i , l i , y i ( 1 ≤ x i ≤ n , 1 ≤ l i ≤ 1 0 9 , 1 ≤ y i ≤ 1 0 5 ) x_i,l_i,y_i(1\leq x_i\leq n,1\leq l_i\leq 10^9,1\leq y_i\leq 10^5) xi,li,yi(1xin,1li109,1yi105) for a query, x i x_i xi is the vertex where Ming started, l i l_i li is the number of steps Ming took, and y i y_i yi is the number in Ming’s hand.

输出
For each query, output a line with an integer representing the answer.The answer could be so large that you have to take mod 1 0 9 + 7 10^9+7 109+7.

#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <functional>
#include <cstring>

using namespace std;

const int N = 100010, mod = 1e9 + 7;

struct Tag {
  int k, b;
  Tag operator+(Tag oth) {
    return Tag {1ll * k * oth.k % mod, (1ll * b * oth.k + oth.b) % mod};
  }
} tag[N][31];
int go[N][31];
int k[N], b[N];

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  int T;
  cin >> T;
  while (T--) {
    int n, q;
    cin >> n >> q;
    for (int i = 1; i <= n; i++) {
      cin >> k[i];
    }
    for (int i = 1; i <= n; i++) {
      cin >> b[i];
    }
    for (int i = 1; i <= n; i++) {
      cin >> go[i][0];
    }
    for (int i = 1; i <= n; i++) {
      tag[i][0] = {k[go[i][0]], b[go[i][0]]};
    }
    for (int j = 1; j <= 30; j++) {
      for (int i = 1; i <= n; i++) {
        tag[i][j] = tag[i][j - 1] + tag[go[i][j - 1]][j - 1];
        go[i][j] = go[go[i][j - 1]][j - 1];
      }
    }
    while (q--) {
      int x, y, l;
      cin >> x >> l >> y;
      Tag t = {1, 0};
      for (int i = 30; ~i; i--) {
        if (l >> i & 1) {
          t = t + tag[x][i];
          x = go[x][i];
        }
      }
      cout << (1ll * t.k * y + t.b) % mod << '\n';
    }
  }
  return 0;
}

1427 Tree(6)

题目描述:
Given a tree of n n n vertices and n − 1 n-1 n1 edges. Each vertex i i i has a color c i c_i ci = ‘a’ or ‘b’ or ‘c’.

Please count the number of simple path between i i i and j j j satisfy :

  • 1 ≤ i ≤ j ≤ n 1 \le i \le j \le n 1ijn
  • The number of vertices with three different colors is equal on the path.

输入:
The first line contains one integer n n n ($ n \le 10^5 $).

The second line contains a string S with length of n n n . ( S i S_i Si represents the color of i i i-th vertex, S i =   ′ a ′   o r   ′ b ′   o r   ′ c ′ S_i = \ 'a' \ or \ 'b' \ or \ 'c' Si= a or b or c)

Each of the next n − 1 n-1 n1 lines contains a pair of vertex indices u i u_i ui and v i v_i vi 1 ≤ u i , v i ≤ n 1\le u_i,v_i \le n 1ui,vin)— endpoints of the corresponding edge.

输出
Output an integer represent the answer.

#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <functional>
#include <map>

using namespace std;

using i64 = long long;

const int N = 100010;

vector<int> adj[N];
int n, k, sz[N], ms[N];
bool vis[N];
string s;

i64 solve(int u, int tot) {
  int rt = u;
  auto get_rt = [&](auto self, int u, int fa) -> void {
    sz[u] = 1, ms[u] = 0;
    for (auto v : adj[u]) {
      if (vis[v] || v == fa) continue;
      self(self, v, u);
      sz[u] += sz[v];
      ms[u] = max(ms[u], sz[v]);
    }
    ms[u] = max(ms[u], tot - sz[u]);
    if (ms[u] <= tot / 2) rt = u;
  };
  get_rt(get_rt, u, 0);
  i64 res = 0;
  vis[u = rt] = true;
  map<array<int, 3>, int> all;
  int ua = -1, ub = -1, uc = -1;
  if (s[u] == 'a') ua += 3;
  if (s[u] == 'b') ub += 3;
  if (s[u] == 'c') uc += 3;
  for (auto v : adj[u]) {
    if (vis[v]) continue;
    map<array<int, 3>, int> sub;
    auto get_info = [&](auto self, int u, int fa, int a, int b, int c) -> void {
      a--, b--, c--;
      if (s[u] == 'a') a += 3;
      if (s[u] == 'b') b += 3;
      if (s[u] == 'c') c += 3;
      if (!a && !b && !c) res++; 
      sub[{a, b, c}]++;
      sz[u] = 1;
      for (auto v : adj[u]) {
        if (vis[v] || v == fa) continue;
        self(self, v, u, a, b, c);
        sz[u] += sz[v];
      }
    };
    get_info(get_info, v, u, ua, ub, uc);
    for (auto [arr, cnt] : sub) {
      auto [a, b, c] = arr;
      res += cnt * all[{-a, -b, -c}];
    }
    for (auto [arr, cnt] : sub) {
      auto [a, b, c] = arr;
      all[{a - ua, b - ub, c - uc}] += cnt;
    }
  }
  for (auto v : adj[u]) {
    if (vis[v]) continue;
    res += solve(v, sz[v]);
  }
  return res;
}

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cin >> n >> s;
  s = ' ' + s;
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    adj[u].emplace_back(v);
    adj[v].emplace_back(u);
  }
  cout << solve(1, n) << '\n';
  return 0;
}


1428 Meadow

题目描述:
There is A N × M N\times M N×M size meadow. For each location ( i , j ) ( 1 ≤ i ≤ N , 1 ≤ j ≤ M ) (i,j)(1\le i\le N,1\le j\le M) (i,j)(1iN,1jM), if A ( i , j ) = 1 A(i,j)=1 A(i,j)=1, it means that this location is planted with grass, and vice versa it means that this location is not planted with grass. If some location ( i , j ) (i,j) (i,j) is covered by a [b]grass-covered[/b](completely covered with grass) square area of size L × L L\times L L×L, the energy of the meadow will increase L × B ( i , j ) L\times B(i,j) L×B(i,j) (the energy can be increased multiple times if a position covered by different square areas that meet the requirements).
You need to calculate the energy of the whole meadow.

输入:
For the first line,input a positive integer T ( 1 ≤ T ≤ 5 ) T(1\le T\le 5) T(1T5), representing the total number of test data.

For each test data, input two positive integers n n n and m m m ( 1 ≤ n , m ≤ 1000 1\leq n,m\leq 1000 1n,m1000) in the first line, representing the size of the meadow.

The next n n n line, each m m m integer, input matrix A ( 0 ≤ A i , j ≤ 1 ) A(0\leq A_{i,j}\le1) A(0Ai,j1), representing whether there is planted with grass in this position.

The next n n n line, each m m m integer, input matrix B ( 0 ≤ B i , j ≤ 1 0 5 ) B(0\leq B_{i,j}\le10^5) B(0Bi,j105), representing the weight of each position.

输出
Output a line of a integer, representing the energy sum of the meadow, the answer may be large, need to modulus 1 0 9 + 7 10^9+7 109+7.
“scanf” and “printf” are slower in this OJ and are not recommended for submission

#include <iostream>
#include <cstring>

using namespace std;

using i64 = long long;

const int N = 1111, mod = 1e9 + 7;

int a[N][N], b[N][N], f[N][N];
int d[N][N], d1[N][N], d2[N][N], d3[N][N], d4[N][N];

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int T;
    cin >> T;
    auto add = [&](int& a, int b) {
        a += b;
        if (a >= mod) a -= mod; 
        if (a < 0) a += mod;
    };
    while (T--) {
        memset(f, 0, sizeof f);
        memset(d, 0, sizeof d);
        memset(d1, 0, sizeof d1);
        memset(d2, 0, sizeof d2);
        memset(d3, 0, sizeof d3); 
        memset(d4, 0, sizeof d4);
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cin >> a[i][j];
                if (a[i][j]) {
                    f[i][j] = min(min(f[i - 1][j], f[i][j - 1]), f[i - 1][j - 1]) + 1;
                }
                int len = f[i][j];
                d1[i - len + 1][j - len + 1] += len;
                d1[i - len + 2][j - len + 2] -= len + 1;
                d1[i + 2][j + 2]++;
                d2[i - len + 1][j + 1] -= len;
                d2[i - len + 2][j + 1] += len + 1;
                d2[i + 2][j + 1]--;
                d3[i + 1][j - len + 1] -= len;
                d3[i + 1][j - len + 2] += len + 1;
                d3[i + 1][j + 2]--;
                d4[i + 1][j + 1] += (len + 1) * len / 2;
            }
        }
        int times = 2;
        while (times--) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    add(d1[i][j], d1[i - 1][j - 1]);
                }
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    add(d2[i][j], d2[i - 1][j]);
                }
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    add(d3[i][j], d3[i][j - 1]);
                }
            }
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                d[i][j] = (1ll * d1[i][j] + d2[i][j] + d3[i][j] + d4[i][j] + 
                        d[i][j - 1] + d[i - 1][j] - d[i - 1][j - 1]) % mod;
            }
        }
        i64 res = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cin >> b[i][j];
                res += 1ll * d[i][j] * b[i][j] % mod;
            }
        }
        res %= mod;
        if (res < 0) res += mod;
        cout << res << '\n';
    }
    return 0;
}


1429 String

题目描述:
Alice and Bob are playing a string game.

Alice has a string S S S, Bob has a string T T T, in each round of the game, Bob will choose a string interval T [ l , r ] T[l,r] T[l,r] in T T T , Alice needs to find a string interval S [ l ′ , r ′ ] S[l',r'] S[l,r] in S S S to make T [ l , r ] T[l,r] T[l,r] is a substring of S [ l ′ , r ′ ] S[l',r'] S[l,r].

We define an interval of pairs [ l , r ] [l,r] [l,r]string S S S if and only if 1 ≤ l ≤ r ≤ S l e n 1\leq l\leq r\leq S_{len} 1lrSlen( S l e n S_{len} Slen is the string S S S length), all optional intervals of a string are all l , r l, r l,r that satisfy the condition. S [ l , r ] S[l,r] S[l,r] is a string formed by concatenating the S S S string from the l l lth character to the r r rth character in order.

A string T T T is a substring of the string S S S if and only if the string T T T can be obtained by removing some characters from the beginning and the end of the string S S S (or not).

Both Alice and Bob find this game too boring, and they want to know if Bob randomly chooses one of all the intervals in the string T T T, how many intervals Alice can choose from the string S S S and such that the string selected by Bob is a substring of the string selected by Alice.

The game will be played multiple times, and in each round, Bob will change the string T T T, so you will need to answer multiple sets of questions.

输入:
For the first line,input a positive integer T ( 1 ≤ T ≤ 5 ) T(1\le T\le 5) T(1T5), representing the total number of test data.

For each test data,the first line contains two positive integers n , q ( 1 ≤ n , q ≤ 100000 ) n,q(1\leq n,q\leq 100000) n,q(1n,q100000), which represent the length of the string and the number of queries.

The second line contains a string of length n n n representing the S S S string owned by Alice.

The next q q q lines, each line contains a string, representing the query string T T T.

It is guarantees that the length of all query strings does not exceed 1 0 6 10^6 106 in one test.

It is guaranteed that the input string contains only English lowercase letters.

输出
For each query, output a line with a positive integer representing the expected number, and the answer modulo 998244353 998244353 998244353.

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

using i64 = long long;

const int N = 100010;
const int mod = 998244353;

int last, tot;
struct Node {
    int fa, len;
    int ch[26];
} node[N * 2];

int qpow(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = 1ll * res * a % mod;
        a = 1ll * a * a % mod;
        b >>= 1;
    }
    return res;
}

int inv(int x) {
    return qpow(x, mod - 2);
}

struct SegTree {
    struct Node {
        int l, r;
        int ls, rs; // leftmost & rightmost position in the endpos set
        int v1, v2; // sum of r_i * r_i / sum of r_i * r_i+1
    } tr[N * 100];
    int root[2 * N], idx;
    
    void init() {
        idx = 0;
        memset(root, 0, sizeof root);
    }
    
    int new_node() {
        int p = ++idx;
        tr[p] = {0, 0, 0, 0, 0, 0};
        return p;
    }
    
    void pushup(int p) {
        tr[p].v1 = (tr[tr[p].l].v1 + tr[tr[p].r].v1) % mod;    
        tr[p].v2 = (tr[tr[p].l].v2 + tr[tr[p].r].v2) % mod;
        tr[p].v2 = (tr[p].v2 + 1ll * tr[tr[p].l].rs * tr[tr[p].r].ls % mod) % mod;
        tr[p].ls = tr[p].l ? tr[tr[p].l].ls : tr[tr[p].r].ls;
        tr[p].rs = tr[p].r ? tr[tr[p].r].rs : tr[tr[p].l].rs;
    }
    
    void insert(int& p, int l, int r, int x) {
        if (!p) p = new_node();
        if (l == r) {
            tr[p].v1 = 1ll * x * x % mod;
            tr[p].ls = tr[p].rs = x;
            return;
        }
        int mid = l + r >> 1;
        if (x <= mid) insert(tr[p].l, l, mid, x);
        else insert(tr[p].r, mid + 1, r, x);
        pushup(p);
    }
    
    int merge(int x, int y, int l, int r) {
        if (!x || !y) return x | y;
        int mid = l + r >> 1;
        tr[x].l = merge(tr[x].l, tr[y].l, l, mid);
        tr[x].r = merge(tr[x].r, tr[y].r, mid + 1, r);
        pushup(x);
        return x;
    }
} s;

void extend(int c) {
    int p = last, np = last = ++tot;
    node[np].len = node[p].len + 1;
    for (; !node[p].ch[c]; p = node[p].fa) node[p].ch[c] = np;
    if (!p) node[np].fa = 1;
    else {
        int q = node[p].ch[c];
        if (node[q].len == node[p].len + 1) node[np].fa = q;
        else {
            int nq = ++tot;
            node[nq] = node[q], node[nq].len = node[p].len + 1;
            node[q].fa = node[np].fa = nq;
            for (; node[p].ch[c] == q; p = node[p].fa) node[p].ch[c] = nq;
        }
    }
}

void init() {
    for (int i = 1; i <= tot; i++) {
        node[i].fa = node[i].len = 0;
        memset(node[i].ch, 0, sizeof node[i].ch);
    }
    last = tot = 1;
    s.init();
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--) {
        init();
        int n, q;
        cin >> n >> q;
        string str;
        cin >> str;
        str = ' ' + str;
        vector<int> pos(11* n + 1);
        for (int i = 1; i <= n; i++) {
            extend(str[i] - 'a');
            pos[last] = i;
            
        }
        vector<vector<int>> adj(tot + 1);
        for (int i = 2; i <= tot; i++) {
            adj[node[i].fa].emplace_back(i);
        }
        vector<int> f1(tot + 1), f2(tot + 1), g(tot + 1);
        auto calc = [&](int l, int r) -> int {
            return 1ll * (l + r) * (r - l + 1) / 2 % mod;  
        };
        auto dfs1 = [&](auto self, int u) -> void { 
            if (pos[u]) {
 
                s.insert(s.root[u], 1, n, pos[u]);
            }
            for (auto v : adj[u]) {
                self(self, v);
                s.root[u] = s.merge(s.root[u], s.root[v], 1, n);
            }
            f1[u] = ((s.tr[s.root[u]].v2 - s.tr[s.root[u]].v1 + 1ll * (n + 1) * s.tr[s.root[u]].rs % mod) % mod + mod) % mod;
            f2[u] = n + 1 - s.tr[s.root[u]].ls;
            int l = node[node[u].fa].len + 1, r = node[u].len;
            g[u] = (1ll * f1[u] * (r - l + 1) % mod - 1ll * calc(l - 1, r - 1) * f2[u] % mod) % mod; 
        };
   
        auto dfs2 = [&](auto self, int u) -> void {
            for (auto v : adj[u]) {
                (g[v] += g[u]) %= mod;
                self(self, v);
            }
        };
        dfs1(dfs1, 1), dfs2(dfs2, 1);  
        while (q--) {
            string t;
            cin >> t;
            int m = t.size(), len = 0, p = 1;
            i64 res = 0;
            for (auto c : t) {
                int u = c - 'a';
                while (p != 1 && !node[p].ch[u]) {
                    p = node[p].fa;
                    len = node[p].len;
                }
                if (node[p].ch[u]) {
                    p = node[p].ch[u];
                    len++;
                }
                if (p != 1) {
                    int l = node[node[p].fa].len + 1, r = len;
                    res += g[node[p].fa] + 1ll * f1[p] * (r - l + 1) % mod - 1ll * calc(l - 1, r - 1) * f2[p] % mod;
                    res %= mod;
                }
            }
            res = (res % mod + mod) % mod;
            res = 1ll * res * inv(1ll * m * (m + 1) / 2 % mod) % mod;
            cout << res << '\n';
        }
    }
    return 0;
}



1430 Alice and Bob

题目描述:
Given an sequence of n n n elements a 1 , a_1, a1, a 2 , a_2, a2, . . . ... ... , a n a_n an.

Alice and Bob will play a game alternating turns with Alice going first.

If the current sequence length is $n $, select a position $pos $ ( 1 ≤ p o s < n 1\le pos < n 1pos<n) to divide the sequence into two part. If the sum of all elements from the first position to the p o s pos pos position is less than the sum of all elements from the p o s + 1 pos+1 pos+1 position to the last position, then delete the first element to the p o s pos pos element. Otherwise, delete the p o s + 1 pos+1 pos+1 element to the n n n element.

When the sequence length after a person’s operation is $1 $, that person wins.

Alice and Bob both want to win. If they can, they hope the element in the final sequence bigger. Otherwise, they hope the element in the final sequence smaller.

Find the answer if both Alice and Bob play optimally

输入:
Each test contains multiple test cases. The first line contains the number of test cases T T T($ T\le 1000 $).
The description of the test cases follows.

The first line contains one integer n n n($1 < n \le 3000 $).

The second line contains n n n integers a 1 ,   a 2 , … ,   a n a_1, \ a_2, \dots , \ a_n a1, a2,, an( $ 1 \le \ a_i \le 10^9 $).

It’s guaranteed that ∑ n ≤ 10000 \sum{n} \le 10000 n10000

输出
For each test case, first print “Alice” or “Bob” means who will win, then print an integer means the final sequence.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

#define fi first
#define se second

using namespace std;

const int N = 3010;

using i64 = long long;
using pii = pair<int, int>;

pii f[N][N];
int k[N][N];
i64 s[N], a[N], n;

// first : win 1 / lose 0 
// second : score

bool operator<=(pii a, pii b) {
    if (a == b) return true;
    if (a.fi == b.fi) {
        if (a.fi == 1) {
            return a.se >= b.se;
        } else {
            return a.se <= b.se;
        }
    } else {
        return a.fi > b.fi;
    }
}

pii max(pii a, pii b) {
    return a <= b ? b : a;
}

struct Queue1 {
    int q[N];
    pii qv[N];
    int tt, hh;
    int type;
    
    void init(int t) {
        tt = -1, hh = 0, type = t;
    }
    
    void push(int pos, pii val) {
        while (hh <= tt && qv[tt] <= val) tt--;
        q[++tt] = pos, qv[tt] =  val;
    }
    
    void pop(int pos) {
        if (type == 0) while (hh <= tt && q[hh] <= pos) hh++;
        if (type == 1) while (hh <= tt && q[hh] >= pos) hh++;
    }
    
    pii val() {
        return qv[hh];
    }
} ql[N], qr[N];

void solve() {
    cin >> n;
    
    for (int i = 1; i <= n; i++) {
        ql[i].init(0), qr[i].init(1);
    }
    
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
        f[i][i] = {0, a[i]};
        qr[i].push(i, f[i][i]);
        ql[i].push(i, f[i][i]);
    }
    
    auto sum = [&](int l, int r) -> i64 {
        return s[r] - s[l - 1];
    };
    
    for (int i = 1; i <= n; i++) {
        k[i][i] = i - 1;
        for (int j = i + 1; j <= n; j++) {
            int& pos = k[i][j];
            pos = k[i][j - 1];
            while (pos + 2 <= j && sum(i, pos + 1) < sum(pos + 2, j)) pos++;
        }
    }
    
    for (int len = 2; len <= n; len++) {
        for (int l = 1, r = l + len - 1; r <= n; l++, r++) {
            int pos = k[l][r];
            if (pos == l - 1) {
                pii tmp = ql[l].val();
                f[l][r] = {!tmp.fi, tmp.se};
            } else if (pos == r - 1) {                
                pii tmp = qr[r].val();
                f[l][r] = {!tmp.fi, tmp.se};
            } else {
                qr[r].pop(pos + 2);
                ql[l].pop(pos);
                pii tmp = max(ql[l].val(), qr[r].val());
                f[l][r] = {!tmp.fi, tmp.se};
            }
            qr[r].push(l, f[l][r]);
            ql[l].push(r, f[l][r]);
        }
    }
    if (f[1][n].first) {
        cout << "Alice ";   
    } else {
        cout << "Bob ";
    }
    cout << f[1][n].second << '\n';
}


int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();    
    }
    return 0;
}

1431 Chords

题目描述:
Imagine a mystical forest where a magic piano with n n n keys resides. Each key of this piano represents a note, denoted by positive integers from 1 1 1 through n n n. In musical terms, a chord is defined as a set of notes played together in harmony. The type or class of a chord is categorized based on the difference between its root note (the lowest note) and the other notes in the chord.

For instance, the chord class known as [i]minor triad[/i] includes all chords of the format { x , x + 3 , x + 7 x, x+3, x+7 x,x+3,x+7}. Similarly, the chord class [i]dominant seventh[/i] includes all chords that follow the pattern { x , x + 4 , x + 7 , x + 10 x, x+4, x+7, x+10 x,x+4,x+7,x+10}.

For each key x x x on the piano (which produces the note x x x), you can play it with a x a_x ax different strengths, each of which produces a unique sound. As a result, you can produce a x a_x ax distinct sounds from that note. More interestingly, for a minor triad with root note x x x as an example, you can produce a x × a x + 3 × a x + 7 a_x \times a_{x+3} \times a_{x+7} ax×ax+3×ax+7 unique sounds.

Now, consider a given chord class represented by { x + b 1 , x + b 2 , . . . , x + b m x + b_1, x+b_2, ..., x+{b_m} x+b1,x+b2,...,x+bm}. Your task is to calculate the total number of different sounds you can produce when you are free to choose any root note x x x.

输入:
The first line of the input contains a single integer T T T ( 1 ≤ T ≤ 1 0 3 1 \leq T \leq 10^3 1T103), denoting the number of test cases.

The first line of each test case contains two integers n , m n,m n,m ( 1 ≤ m ≤ n ≤ 5 × 1 0 5 1 \leq m \leq n \leq 5\times 10^5 1mn5×105) separated by space, denoting the number of keys in the piano and the number of notes in the given chord class.

The second line of each test case contains n n n positive integers a 1 , … , a n a_1, \ldots, a_n a1,,an ( 0 < a x < 1062125569 0 < a_x < 1062125569 0<ax<1062125569), each representing the number of different strengths that can be applied to the corresponding key x x x.

The third line of each test case contains m m m ascending integers b 1 , … , b m b_1, \ldots, b_m b1,,bm ( 0 = b 1 < b 2 < … < b m < n 0 = b_1 < b_2 < \ldots < b_m < n 0=b1<b2<<bm<n), denoting the given chord class.

It is guaranteed that the sum of n n n over all test cases will not exceed 1 0 6 10 ^ 6 106.

输出
For each test case, output the answer modulo 1062125569 1062125569 1062125569 in a single line.

#include<bits/stdc++.h>

using namespace std;

#define gc c=getchar()
#define ll long long

template<typename T>
inline void read(T &x){
	x=0;T k=1;char gc;
	while(!isdigit(c)){if(c=='-')k=-1;gc;}
	while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
}

inline ll qpow(ll a, int b, int p){
	a %= p;
	b %= p - 1;
	ll ans = 1;
	while(b){
		if(b & 1) (ans *= a) %= p;
		(a *= a) %= p;
		b >>= 1;
	}
	return ans;
}

void exgcd(int a, int b, int &x, int &y){
	if(b){
		exgcd(b, a % b, x, y);
		int t = x;
		x = y;
		y = t - a / b * y;
	}
	else{
		x = 1, y = 0;
	}
}

inline ll inv(int a, int b){
	int x, y;
	exgcd(a, b, x, y);
	return (x % b + b) % b;
}

int CRT(const vector<int> &f, const vector<int> &coef, const int p){
	int ans = 0;
	for(int i = 0; i < f.size(); ++i){
		ans = (ans + (ll)f[i] * coef[i]) % p;
	}
	return ans;
}

struct Pohlig_Hellman{
	const int mod;
	const int n;
	int g;
	vector<int>factor_p;
	vector<int>factor_pk;
	vector<int>crt_coef;
	vector<unordered_map<int, int>> ans;
	
	Pohlig_Hellman(int mod) : mod(mod), n(mod - 1) { // n = phi(mod)
		int nn = n;
		for(int i = 2; i * i <= nn; ++i){
			if(nn % i == 0){
				int pk = 1;
				while(nn % i == 0){
					nn /= i;
					pk *= i;
				}
				factor_p.push_back(i);
				factor_pk.push_back(pk);
			}
		}
		if(nn != 1){
			factor_p.push_back(nn);
			factor_pk.push_back(nn);
		}
		for(g = 2; ; ++g){
			bool flag = 1;
			for(auto &p: factor_p){
				if(qpow(g, n / p, mod) == 1){
					flag = 0;
					break;
				}
			}
			if(flag) break;
		}
		ans.resize(factor_pk.size());
		for(int i = 0; i < factor_pk.size(); ++i){
			int pk = factor_pk[i];
			ll t = 1;
			ll gg = qpow(g, n / pk, mod);
			for(int j = 0; j < pk; ++j){
				ans[i][t] = j;
                t = t * gg % mod;
			}
		}
		for(int i = 0; i < factor_pk.size(); ++i){
			crt_coef.push_back((n / factor_pk[i]) * inv(n / factor_pk[i], factor_pk[i]) % n);
		}
	}

	int calc(int x){
		vector<int> X;
		for(int i = 0; i < factor_pk.size(); ++i){
			int pk = factor_pk[i];
			int b = qpow(x, n / pk, mod);
			X.push_back(ans[i][b]);
		}
		return CRT(X, crt_coef, n);
	}
};

#define db double
struct comp{
    db r,i;
    comp(){}
    comp(const db &_r,const db &_i):r(_r),i(_i){}
};

inline comp operator + (const comp &a,const comp &b){
    return comp(a.r+b.r,a.i+b.i);
}

inline comp operator - (const comp &a,const comp &b){
    return comp(a.r-b.r,a.i-b.i);
}

inline comp operator * (const comp &a,const comp &b){
    return comp(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);
}

inline comp operator / (const comp &a,const db &b){
    return comp(a.r/b,a.i/b);
}

inline comp conj(const comp &a){
    return comp(a.r,-a.i);
}

const db PI=acos(-1.0);
const int N=2e6+7;

int rev[N];
comp Wn[N];
int Now_Len;
inline void revinit(int n){
    for(int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)*(n>>1));
    for(int i=0;i<n;++i)Wn[i]=comp(cos(PI*i/n),sin(PI*i/n));
    Now_Len=n;
}

inline void DFT(comp *A,int n){
    if(Now_Len!=n)revinit(n);
    for(int i=0;i<n;++i)if(i<rev[i])swap(A[i],A[rev[i]]);
    for(int i=1;i<n;i<<=1){
        for(int j=0;j<n;j+=i<<1){
            for(int k=0;k<i;++k){
                comp u=A[j+k],v=A[i+j+k]*Wn[n/i*k];
                A[j+k]=u+v;
                A[i+j+k]=u-v;
            }
        }
    }
}

inline void IDFT(comp *A,int n){
    if(Now_Len!=n)revinit(n);
    for(int i=0;i<n;++i)if(i<rev[i])swap(A[i],A[rev[i]]);
    for(int i=1;i<n;i<<=1){
        for(int j=0;j<n;j+=i<<1){
            for(int k=0;k<i;++k){
                comp u=A[j+k],v=A[i+j+k]*conj(Wn[n/i*k]);
                A[j+k]=u+v;
                A[i+j+k]=u-v;
            }
        }
    }
    for(int i=0;i<n;++i){
    	A[i]=A[i]/n;
    }
}

#define DFT(A) DFT(A,n)
#define IDFT(A) IDFT(A,n)

const int p = 1062125569;

comp Ta[N],Tb[N],Tc[N],Td[N];
inline void MTT(int *A,int *B,int *C,int lenA,int lenB){
    int lenC=lenA+lenB-1,n;
    if(lenC<=256){
    	memset(C,0,lenC<<2);
    	for(int i=0;i<lenA;++i){
    		for(int j=0;j<lenB;++j){
    			C[i+j]=(C[i+j]+(ll)A[i]*B[j])%(p-1);
    		}
    	}
    	return ;
    }
    for(n=1;n<lenC;n<<=1);
    for(int i=0;i<lenA;++i)Ta[i]=comp(A[i]&32767,A[i]>>15);
    for(int i=0;i<lenB;++i)Tb[i]=comp(B[i]&32767,B[i]>>15);
	for(int i=lenA;i<n;++i)Ta[i]=comp(0,0);
	for(int i=lenB;i<n;++i)Tb[i]=comp(0,0);
    DFT(Ta);DFT(Tb);
    for(int i=0;i<n;++i){
        int j=(n-i)&(n-1);
        comp A0=(Ta[i]+conj(Ta[j]))*comp(0.5,0);
        comp A1=(Ta[i]-conj(Ta[j]))*comp(0,-0.5);
        comp B0=(Tb[i]+conj(Tb[j]))*comp(0.5,0);
        comp B1=(Tb[i]-conj(Tb[j]))*comp(0,-0.5);
        Tc[i]=A0*B0+A0*B1*comp(0,1);
        Td[i]=A1*B0+A1*B1*comp(0,1);
    }
    IDFT(Tc);IDFT(Td);
    for(int i=0;i<n;++i){
        ll s1=(ll)(Tc[i].r+0.5)%(p-1);
        ll s2=(ll)(Tc[i].i+0.5)%(p-1);
        ll s3=(ll)(Td[i].r+0.5)%(p-1);
        ll s4=(ll)(Td[i].i+0.5)%(p-1);
        C[i]=(s1+((s2+s3)<<15)+(s4<<30))%(p-1);
    }
}

int a[N];
int b[N];
int c[N];
int d[N];
int f[N];
Pohlig_Hellman t(p);

inline void solve(){
    int n, m; read(n), read(m);
	for(int i = 0; i < n; ++i){
		read(a[i]);
		d[i] = t.calc(a[i]);
	}
	for(int i = 1; i <= m; ++i){
		read(b[i]);
	}
	for(int i = 0; i <= b[m]; ++i){
		c[i] = 0;
	}
	for(int i = 1; i <= m; ++i){
		c[b[m] - b[i]] = 1;
	}

	MTT(d, c, f, n, b[m] + 1);
	ll ans = 0;
	for(int i = 0; i + b[m] < n; ++i){
		ans += qpow(t.g, f[i + b[m]], p);
	}
	printf("%lld\n", ans % p);
}

int main(){
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	// cerr << t.g << endl;
	int T; read(T);
	while(T--){
	    solve();   
	}
	return 0;
}

1432 Delivery Robot

题目描述:
A delivery robot is an autonomous machine designed to provide delivery services. On many campuses, these robots can offer significant convenience to students.

A delivery robot typically integrates various assistance systems, such as collision avoidance systems. These systems should enable the robot to automatically avoid both static obstacles and other robots. Due to the non-immediate nature of velocity control, collision avoidance systems typically allocate a time interval Δ t \Delta t Δt. If a collision is predicted to occur within Δ t \Delta t Δt at the current velocity, the system adjusts the robot’s velocity accordingly, including its speed and direction.

We assume that the velocity can change instantly at the beginning of Δ t \Delta t Δt but remains constant throughout Δ t \Delta t Δt. In this problem, we set Δ t = 1 \Delta t=1 Δt=1, meaning you only need to consider the first Δ t = 1 \Delta t=1 Δt=1 from the initial position, without considering the subsequent process.

We envision the delivery robot as a moving convex polygon on a two-dimensional plane with n n n vertices, with its initial vertex coordinates given. In addition, there is a stationary convex polygonal obstacle on the plane with m m m vertices, and its vertex coordinates are also given.

As a developer of the collision avoidance system, you want to conduct q q q tests, each time setting an initial velocity vector v \bf{v} v for the robot, and the robot will start from the given initial position. According to the principle of the collision avoidance system, if the robot will collide with the obstacle after traveling for Δ t = 1 \Delta t=1 Δt=1 at the current velocity, the robot’s velocity should be changed immediately at the beginning, that is, v \bf{v} v should be modified to v ′ \bf{v}' v.

Without an upper limit on speed, it is evident that a suitable v ′ \bf{v}' v must exist to prevent a collision within Δ t = 1 \Delta t=1 Δt=1. Depending on the situation, different strategies can be used to select v ′ \bf{v}' v. The objective of this problem is to choose a v ′ \bf{v}' v that minimizes the magnitude of the difference between v \bf{v} v and v ′ \bf{v}' v, i.e. v ′ = arg ⁡ min ⁡ u ∥ v − u ∥ \bf{v}'=\arg\min_{\bf{u}}\Vert {\bf{v}}-{\bf{u}}\Vert v=argminuvu. The magnitude of a vector v = ( x , y ) {\bf{v}}=(x,y) v=(x,y) is defined as ∥ v ∥ = x 2 + y 2 \Vert{\bf{v}}\Vert=\sqrt{x^2+y^2} v=x2+y2 .

输入:
The first line contains an integer T T T ( 1 ≤ T ≤ 20 1\le T \le 20 1T20), indicating the number of test cases.

The first line of each test case contains three integers n , m , q n,m,q n,m,q ( 3 ≤ n , m , q ≤ 1000 3 \le n,m,q \le 1000 3n,m,q1000), indicating the number of vertices of the delivery robot and the obstacle, respectively.

Each of the next n n n lines contains two integers x , y x,y x,y ( − 1 0 6 ≤ x , y ≤ 1 0 6 -10^6 \le x,y \le 10^6 106x,y106), indicating the coordinates of a vertex of the delivery robot. The coordinates are given in counter-clockwise order.

Each of the next m m m lines contains two integers x , y x,y x,y ( − 1 0 6 ≤ x , y ≤ 1 0 6 -10^6 \le x,y \le 10^6 106x,y106), indicating the coordinates of a vertex of the obstacle. The coordinates are given in counter-clockwise order. It is guaranteed that the delivery robot and the obstacle are strictly disjoint.

Each of the next q q q lines contains two integers x , y x,y x,y ( − 1 0 6 ≤ x , y ≤ 1 0 6 -10^6 \le x,y \le 10^6 106x,y106), indicating the initial velocity vector v = ( x , y ) {\bf{v}}=(x,y) v=(x,y) of the delivery robot.

It is guaranteed that ∑ n ≤ 2000 \sum n \le 2000 n2000 and ∑ m ≤ 2000 \sum m \le 2000 m2000 and ∑ q ≤ 5000 \sum q \le 5000 q5000 over all test cases.

输出
For each test, output the [b]square[/b] of the minimum magnitude of v − v ′ {\bf{v}}-{\bf{v}}' vv, i.e. min ⁡ ∥ v − v ′ ∥ 2 \min\Vert{\bf{v}}-{\bf{v}}'\Vert^2 minvv2, in a single line. You should output the answer as an irreducible fraction p / q p/q p/q, where p p p, q q q are integers and q > 0 q > 0 q>0.

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

using point_t=long long;  

constexpr point_t eps=1e-8;
constexpr long double PI=3.1415926535897932384l;

__int128 gcd(__int128 a,__int128 b)
{
    if (b==0) return a;
    return gcd(b,a%b);
}


template<typename T> struct point
{
    T x,y;

    bool operator==(const point &a) const {return (abs(x-a.x)<=eps && abs(y-a.y)<=eps);}
    bool operator<(const point &a) const {if (abs(x-a.x)<=eps) return y<a.y-eps; return x<a.x-eps;}
    bool operator>(const point &a) const {return !(*this<a || *this==a);}
    point operator+(const point &a) const {return {x+a.x,y+a.y};}
    point operator-(const point &a) const {return {x-a.x,y-a.y};}
    point operator-() const {return {-x,-y};}
    point operator*(const T k) const {return {k*x,k*y};}
    point operator/(const T k) const {return {x/k,y/k};}
    T operator*(const point &a) const {return x*a.x+y*a.y;}  // 鐐圭Н
    T operator^(const point &a) const {return x*a.y-y*a.x;}  // 鍙夌Н锛屾敞鎰忎紭鍏堢骇
    int toleft(const point &a) const {const auto t=(*this)^a; return (t>eps)-(t<-eps);}  // to-left 娴嬭瘯
    T len2() const {return (*this)*(*this);}  // 鍚戦噺闀垮害鐨勫钩鏂?
    T dis2(const point &a) const {return (a-(*this)).len2();}  // 涓ょ偣璺濈鐨勫钩鏂?
};

using Point=point<point_t>;

// 鏋佽鎺掑簭
struct argcmp
{
    bool operator()(const Point &a,const Point &b) const
    {
        const auto quad=[](const Point &a)
        {
            if (a.y<-eps) return 1;
            if (a.y>eps) return 4;
            if (a.x<-eps) return 5;
            if (a.x>eps) return 3;
            return 2;
        };
        const int qa=quad(a),qb=quad(b);
        if (qa!=qb) return qa<qb;
        const auto t=a^b;
        // if (abs(t)<=eps) return a*a<b*b-eps;  // 涓嶅悓闀垮害鐨勫悜閲忛渶瑕佸垎寮€
        return t>eps;
    }
};

// 鐩寸嚎
template<typename T> struct line
{
    point<T> p,v;  // p 涓虹洿绾夸笂涓€鐐癸紝v 涓烘柟鍚戝悜閲?

    bool operator==(const line &a) const {return v.toleft(a.v)==0 && v.toleft(p-a.p)==0;}
    int toleft(const point<T> &a) const {return v.toleft(a-p);}  // to-left 娴嬭瘯
    bool operator<(const line &a) const  // 鍗婂钩闈氦绠楁硶瀹氫箟鐨勬帓搴?
    {
        if (abs(v^a.v)<=eps && v*a.v>=-eps) return toleft(a.p)==-1;
        return argcmp()(v,a.v);
    }

    pair<__int128,__int128> dis2(const point<T> &a) const
    {
        const auto t=v^(a-p);
        const __int128 x=(__int128)t*t;
        const __int128 y=v.len2();
        const __int128 g=gcd(x,y);
        return {x/g,y/g};
    } 

    // long double dis(const point<T> &a) const {return abs(v^(a-p))/v.len();}  // 鐐瑰埌鐩寸嚎璺濈
};

using Line=line<point_t>;

//绾挎
template<typename T> struct segment
{
    point<T> a,b;

    pair<__int128,__int128> dis2(const point<T> &p) const
    {
        if ((p-a)*(b-a)<-eps || (p-b)*(a-b)<-eps) return {min(p.dis2(a),p.dis2(b)),1};
        const line<T> l{a,b-a};
        return l.dis2(p);
    }

    // // 鐐瑰埌绾挎璺濈
    // long double dis(const point<T> &p) const
    // {
    //     if ((p-a)*(b-a)<-eps || (p-b)*(a-b)<-eps) return min(p.dis(a),p.dis(b));
    //     const line<T> l{a,b-a};
    //     return l.dis(p);
    // }
};

using Segment=segment<point_t>;

// 澶氳竟褰?
template<typename T> struct polygon
{
    vector<point<T>> p;  // 浠ラ€嗘椂閽堥『搴忓瓨鍌?

    size_t nxt(const size_t i) const {return i==p.size()-1?0:i+1;}
    size_t pre(const size_t i) const {return i==0?p.size()-1:i-1;}
};

using Polygon=polygon<point_t>;

//鍑稿杈瑰舰
template<typename T> struct convex: polygon<T>
{
    // 闂靛彲澶柉鍩哄拰
    convex operator+(const convex &c) const  
    {
        const auto &p=this->p;
        vector<Segment> e1(p.size()),e2(c.p.size()),edge(p.size()+c.p.size());
        vector<point<T>> res; res.reserve(p.size()+c.p.size());
        const auto cmp=[](const Segment &u,const Segment &v) {return argcmp()(u.b-u.a,v.b-v.a);};
        for (size_t i=0;i<p.size();i++) e1[i]={p[i],p[this->nxt(i)]};
        for (size_t i=0;i<c.p.size();i++) e2[i]={c.p[i],c.p[c.nxt(i)]};
        rotate(e1.begin(),min_element(e1.begin(),e1.end(),cmp),e1.end());
        rotate(e2.begin(),min_element(e2.begin(),e2.end(),cmp),e2.end());
        merge(e1.begin(),e1.end(),e2.begin(),e2.end(),edge.begin(),cmp);
        const auto check=[](const vector<point<T>> &res,const point<T> &u)
        {
            const auto back1=res.back(),back2=*prev(res.end(),2);
            return (back1-back2).toleft(u-back1)==0 && (back1-back2)*(u-back1)>=-eps;
        };
        auto u=e1[0].a+e2[0].a;
        for (const auto &v:edge)
        {
            while (res.size()>1 && check(res,u)) res.pop_back();
            res.push_back(u);
            u=u+v.b-v.a;
        }
        if (res.size()>1 && check(res,res[0])) res.pop_back();
        return {res};
    }

    // 杩囧嚫澶氳竟褰㈠涓€鐐规眰鍑稿杈瑰舰鐨勫垏绾匡紝杩斿洖鍒囩偣涓嬫爣
    pair<size_t,size_t> tangent(const point<T> &a) const
    {
        const auto &p=this->p;
        size_t l=-1,r=-1;
        for (size_t i=0;i<p.size();i++)
        {
            const Point u=p[i],preu=p[this->pre(i)],nxtu=p[this->nxt(i)];
            const Line t={a,u-a};
            if (t.toleft(preu)>=0 && t.toleft(nxtu)>=0) r=i;
            if (t.toleft(preu)<=0 && t.toleft(nxtu)<=0) l=i;
        }
        return {l,r};
    }
};

using Convex=convex<point_t>;

vector<pair<__int128,__int128>> solve(const Convex &a,const Convex &b,const vector<Point> &query)
{
    const Point o={0,0};
    Convex _a=a;
    for (Point &u:_a.p) u=-u;
    const Convex c=_a+b;
    // for (const Point &p:c.p) cerr<<p.x<<' '<<p.y<<'\n';
    const auto [l,r]=c.tangent(o);
    const Line tl={o,c.p[l]-o},tr={o,c.p[r]-o};
    vector<pair<__int128,__int128>> ans;
    for (const Point &v:query)
    {
        if (tl.toleft(v)>=0 || tr.toleft(v)<=0)
        {
            ans.push_back({0,1});
            continue;
        }
        const Line lr={c.p[l],c.p[r]-c.p[l]};
        if (lr.toleft(v)<0)
        {
            bool in=true;
            for (size_t i=l;i!=r;i=c.nxt(i))
            {
                const Line e={c.p[i],c.p[c.nxt(i)]-c.p[i]};
                if (e.toleft(v)<=0)
                {
                    in=false;
                    break;
                } 
            }
            if (!in)
            {
                ans.push_back({0,1});
                continue;
            }
        }
        const auto [xl,yl]=tl.dis2(v);
        const auto [xr,yr]=tr.dis2(v);
        __int128 minx=1,miny=0;
        if (xl*miny<minx*yl) minx=xl,miny=yl;
        if (xr*miny<minx*yr) minx=xr,miny=yr;
        for (size_t i=l;i!=r;i=c.nxt(i))
        {
            const Segment e={c.p[i],c.p[c.nxt(i)]};
            const auto [x,y]=e.dis2(v);
            if (x*miny<minx*y) minx=x,miny=y;
        }
        const auto g=gcd(minx,miny);
        ans.push_back({minx/g,miny/g});
    }
    return ans;
}

void print(__int128 x)
{
    if (!x)
    {
        putchar('0');
        return;
    }
    vector<int> digits;
    while (x)
    {
        digits.push_back(x%10);
        x/=10;
    }
    reverse(digits.begin(),digits.end());
    for (const auto d:digits) putchar('0'+d);
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int n,m,q;
        scanf("%d%d%d",&n,&m,&q);
        vector<Point> va(n),vb(m);
        for (int i=0;i<n;i++)
        {
            long long x,y;
            scanf("%lld%lld",&x,&y);
            va[i]={x,y};
        }
        for (int i=0;i<m;i++)
        {
            long long x,y;
            scanf("%lld%lld",&x,&y);
            vb[i]={x,y};
        }
        Convex a{va},b{vb};
        vector<Point> query(q);
        for (int i=0;i<q;i++)
        {
            long long x,y;
            scanf("%lld%lld",&x,&y);
            query[i]={x,y};
        }
        const auto ans=solve(a,b,query);
        for (const auto [x,y]:ans)
        {
            print(x);
            putchar('/');
            print(y);
            putchar('\n');
        }
    }
    return 0;
}

1433 Congruences

题目描述:
Your task is to solve a system of m m m congruences, each one represented in the following format:

x p i ≡ q i ( m o d n ) ( i = 1 , 2 , . . . , m ) x ^ {p_i} \equiv q_i \pmod n \quad (i = 1, 2, ..., m) xpiqi(modn)(i=1,2,...,m)

Here, p i p_i pi refers to [b]pairwise distinct[/b] prime numbers, n n n is the product of all p i p_i pi (i.e., n = ∏ i = 1 m p i n = \prod_{i=1}^{m} p_i n=i=1mpi), and q i q_i qi is an integer within the range of [ 0 , n ) [0, n) [0,n).

The goal is to find the [b]smallest positive[/b] integer x x x that fulfills all given congruences. If there is no solution exists for the given system of congruences, output − 1 -1 1.

输入:
The first line contains a positive integer T T T ( 1 ≤ T ≤ 1 0 4 1 \le T \le 10^4 1T104), indicating the number of test cases.

For each test case, the first line contains a positive integer m m m, and each of the following m m m lines contains two integers p i p_i pi and q i q_i qi ( 2 ≤ p i ≤ 1 0 18 2\le p_i\le 10^{18} 2pi1018, 0 ≤ q i < n 0\le q_i < n 0qi<n). It is guaranteed that n = ∏ i = 1 m p i ≤ 1 0 18 n = \prod_{i=1}^{m} p_i \le 10^{18} n=i=1mpi1018.

输出
For each test case, output a single positive integer x x x representing the answer or output − 1 -1 1.

#include<bits/stdc++.h>

using namespace std;

#define gc c=getchar()
#define r(x) read(x)
#define ll long long

template<typename T>
inline void read(T &x){
	x=0;T k=1;char gc;
	while(!isdigit(c)){if(c=='-')k=-1;gc;}
	while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
}

inline ll qpow(__int128 a, ll b, ll p){
	__int128 ans = 1;
	while(b){
		if(b & 1) (ans *= a) %= p;
		(a *= a) %= p;
		b >>= 1;
	}
	return ans;
}

inline ll inv(ll x, ll p){
	return qpow(x % p, p - 2, p);
}

ll CRT(const vector<ll> &f, const vector<ll> &m, const ll n){
	ll ans = 0;
	for(int i = 0; i < f.size(); ++i){
		ans += (__int128)f[i] * (n / m[i]) * inv(n / m[i], m[i]) % n;
	}
	return ans % n;
}

void solve(){
	int m; r(m);
	ll n = 1;
	map<ll, ll> mp;
	vector<ll> A;
	vector<ll> B;
	vector<ll> C;
	for(int i = 0; i < m; ++i){
		ll a, b; r(a), r(b);
		if(mp.find(a) != mp.end()){
			assert(mp[a] == b);
		}
		else{
			mp[a] = b;
			A.push_back(a);
			B.push_back(b % a);
			C.push_back(b);
		}
		n *= a;
	}
	assert(n <= 1e18);
	ll ans = CRT(B, A, n);
	for(int i = 0; i < m; ++i){
		// cerr << qpow(ans, A[i], n) << endl;
		// cerr << C[i] << endl;
// 		assert(qpow(ans, A[i], n) == C[i]);
        if(qpow(ans, A[i], n) != C[i]){
            puts("-1");
            return ;
        }
	}
	if(ans == 0) ans = n;
	printf("%lld\n", ans);
}

int main(){
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	int T; r(T);
	while(T--){
		solve();
	}
	return 0;
}

1434 GG and YY’s Binary Number

题目描述:
GG and YY are honing their skills with binary numbers. They have a set V V V comprising n n n binary numbers: V = { v 1 , v 2 , … , v n } V = \{v_1, v_2, \ldots, v_n\} V={v1,v2,,vn}. Additionally, they have m m m queries determined by intervals [ l 1 , r 1 ] , [ l 2 , r 2 ] , … , [ l m , r m ] [l_1, r_1], [l_2, r_2], \ldots, [l_m, r_m] [l1,r1],[l2,r2],,[lm,rm]. For each query interval [ l i , r i ] [l_i, r_i] [li,ri], they aim to compute the count of unique subsets U U U taken from V V V such that the xor sum of the elements of U U U lies within [ l i , r i ] [l_i, r_i] [li,ri]. The results should be provided modulo 1 0 9 + 7 10^9 + 7 109+7.

Specifically, for each [ l i , r i ] [l_i, r_i] [li,ri], compute:

( ∑ j ∈ [ l i , r i ] ∑ { u 1 , u 2 , … , u k } ⊆ V [ u 1 ⊕ u 2 ⊕ … ⊕ u k = j ] )   m o d   ( 1 0 9 + 7 ) \left( \sum_{j \in [l_i, r_i]} \sum_{\{u_1, u_2, \ldots, u_k\} \subseteq V} [u_1 \oplus u_2 \oplus \ldots \oplus u_k = j] \right) \bmod (10^9 + 7) j[li,ri]{u1,u2,,uk}V[u1u2uk=j] mod(109+7)

where ⊕ \oplus represents the xor operation and square brackets [ ⋅ ] [\cdot] [] denote the Iverson bracket. Please note that the xor sum of an empty set is 0 0 0.

In the Iverson bracket notation, if the condition inside the bracket is true, the value is 1 1 1; otherwise, it is 0 0 0. For instance, [ u 1 ⊕ u 2 ⊕ … ⊕ u k = j ] [u_1 \oplus u_2 \oplus \ldots \oplus u_k = j] [u1u2uk=j] is 1 1 1 if the xor sum of u 1 , u 2 , … , u k u_1, u_2, \ldots, u_k u1,u2,,uk equals j j j, and 0 0 0 otherwise.

输入:
The first line contains one integer t t t ( 1 ≤ t ≤ 100 1 \le t \le 100 1t100), indicating the number of test cases.

The first line of each case contains two integers n n n and m m m ( 1 ≤ n , m ≤ 250 1\le n,m\le 250 1n,m250), indicating the size of the sets V V V and W W W.

The following line contains n n n binary integers v 1 , … , v n v_1,\ldots,v_n v1,,vn ( 0 ≤ v i < 2 250 0\le v_i< 2^{250} 0vi<2250), indicating the binary integers in V V V.

The following m m m lines present the m m m queries. The i i i-th line continas two binary integers l i , r i l_i,r_i li,ri ( 0 ≤ l i ≤ r i < 2 250 0\le l_i\le r_i<2^{250} 0liri<2250), indicating the query interval.

It is guaranteed that there will be no leading zeros in the binary numbers, with the exception of 0 0 0. For instance, the binary number 110 110 110 corresponds to the decimal number 6 6 6.

输出
For each test case, output m m m integers in m m m lines, indicating the results of the queries.

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <bitset>
#include <vector>
#include <cstring>
using namespace std;
 
const int EQ_SIZE = 250;
struct ZeroOneLinearEquation {
    vector<unsigned long long> f;
    ZeroOneLinearEquation() {
        f = vector<unsigned long long>((EQ_SIZE + 63) / 64, 0);
    }
    void set(int x) {
        f[x / 64] |= 1ULL << (x % 64);
    }
    void reset(int x) {
        f[x / 64] &= ~(1ULL << (x % 64));
    }
    bool get(int x) const {
        return f[x / 64] & (1ULL << (x % 64));
    }
    bool is_all_zeros() const {
        for (int i = 0; i < (int)f.size(); ++ i) {
            if (f[i]) {
                return false;
            }
        }
        return true;
    }
 
    int highest_bit() const {
        for (int i = (int)f.size() - 1; i >= 0; -- i) {
            if (f[i]) {
                return i * 64 + __builtin_clzll(f[i]) ^ 63;
            }
        }
        return -1;
    }
};
 
ZeroOneLinearEquation operator^(const ZeroOneLinearEquation &a, const ZeroOneLinearEquation &b) {
    ZeroOneLinearEquation c;
    for (int i = 0; i < (int)a.f.size(); ++ i) {
        c.f[i] = a.f[i] ^ b.f[i];
    }
    return c;
}
 
struct ZeroOneLinearEquationSystem {
    vector<ZeroOneLinearEquation> equations;
    vector<int> id_bit;
    ZeroOneLinearEquationSystem() {
        equations.clear();
        id_bit.clear();
    }
 
    void add(const ZeroOneLinearEquation &equation) {
        equations.push_back(equation);
    }
 
    void get_basis() {
        int l = 0;
        for (int i = EQ_SIZE - 1; i >= 0; -- i) {
            int j = l;
            while (j < (int)equations.size() && !equations[j].get(i)) {
                ++ j;
            }
            if (j < (int)equations.size()) {
                swap(equations[l], equations[j]);
                for (int k = l + 1; k < (int)equations.size(); ++ k) {
                    if (equations[k].get(i)) {
                        equations[k] = equations[k] ^ equations[l];
                    }
                }
                for (int k = 0; k < l; k ++) {
                    if (equations[k].get(i)) {
                        equations[k] = equations[k] ^ equations[l];
                    }
                }
                id_bit.push_back(i);
                ++ l;
            }
        }
        equations.resize(l);
    }
 
    bool can_describe(ZeroOneLinearEquation equation) {
        for (int i = 0; i < (int)equations.size(); ++ i) {
            if (equation.get(id_bit[i])) {
                equation = equation ^ equations[i];
            }
        }
        return equation.is_all_zeros();
    }
};
 
ZeroOneLinearEquation read_a_equation() {
    ZeroOneLinearEquation equation;
    static char s[1000];
    scanf(" %s", s);
    int n = strlen(s);
    reverse(s, s + n);
    for (int i = 0; i < n; ++ i) {
        if (s[i] == '1') {
            equation.set(i);
        }
    }
    return equation;
}
 
ZeroOneLinearEquationSystem es;
const int MOD = 1e9 + 7;
 
long long pow2[301];
 
bool operator>(const ZeroOneLinearEquation& a, const ZeroOneLinearEquation& b) {
    for (int i = (int)a.f.size() - 1; i >= 0 ; -- i) {
        if (a.f[i] > b.f[i]) {
            return true;
        } else if (a.f[i] < b.f[i]) {
            return false;
        }
    }
    return false;
}
 
long long compute(ZeroOneLinearEquation& a, ZeroOneLinearEquation& b, int x) {
    if (x == (int)es.id_bit.size()) {
        return 1;
    }
    ZeroOneLinearEquation c = a ^ b;
    if (c.is_all_zeros()) {
        return 1;
    }
    if (c.highest_bit() < es.id_bit[x]) {
        return compute(a, b, x + 1);
    } else if (c.highest_bit() > es.id_bit[x]) {
        return pow2[es.id_bit.size() - x];
    } else {
        ZeroOneLinearEquation new_b = b ^ es.equations[x];
        if (new_b > a) {
            return compute(a, b, x + 1);
        } else {
            return (pow2[es.id_bit.size() - x - 1] + compute(a, new_b, x + 1)) % MOD;
        }
    }
 
}
 
 
 
 
int main() {    
    int T;
    scanf("%d", &T);
    pow2[0] = 1;
    for (int i = 1; i <= 300; ++ i) {
        pow2[i] = pow2[i - 1] * 2 % MOD;
    }
    ZeroOneLinearEquation empty;
    while (T --) {
        int n, m;
        scanf("%d %d", &n, &m);
        es.equations.clear();
        es.id_bit.clear();
        for (int i = 0; i < n; i ++){
            ZeroOneLinearEquation equation = read_a_equation();
            es.add(equation);
        }
        es.get_basis();
        for (int i = 0; i < m; i ++) {
            ZeroOneLinearEquation l = read_a_equation(), r = read_a_equation();
            if (!l.is_all_zeros()) {
                for (int j = 0; j < EQ_SIZE; j ++) {
                    if (l.get(j)) {
                        l.reset(j);
                        break;
                    } else {
                        l.set(j);
                    }
                }
                printf("%lld\n", (compute(r, empty, 0) - compute(l, empty, 0) + MOD) % MOD * pow2[n - es.id_bit.size()] % MOD);
            } else {
                printf("%lld\n", compute(r, empty, 0) * pow2[n - es.id_bit.size()] % MOD);
            }
        }
    }
 
    return 0;
}
 

1435 0 vs 1

题目描述:
Two players named Zero and One are playing a strategic game with a string of characters consisting of only 0 \texttt{0} 0s and 1 \texttt{1} 1s.

The rules of the game are as follows:

  • The players take turns removing a single character from either the left or the right end of the string, starting with the player named Zero.
  • If Zero picks a 1 \texttt{1} 1, he lose the game. Similarly, if One picks a 0 \texttt{0} 0, he loses the game.
  • If all characters in the string are removed and no one has lost, the game ends in a draw.

    If both players are playing optimally, your task is to determine who will win the game, or whether the game will end in a draw.

输入:
The first line contains a single integer T T T ( 1 ≤ T ≤ 150 1\le T\le 150 1T150), denoting the number of test cases.

The first line of each test case consists of an integer n n n ( 1 ≤ n ≤ 1 0 5 1\le n\le 10^5 1n105), denoting the length of the string.

The second line contains a string of length n n n consisting of only 0 \texttt{0} 0s and 1 \texttt{1} 1s, denoting the initial string of the game.

It is guaranteed that there are no more than 50 50 50 test cases with n > 100 n>100 n>100.

输出
For each test case, output a integer in a single line. If One will win the game, output 1 1 1. If Zero will win the game, output 0 0 0. If the game will end in a draw, output − 1 -1 1.

#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e6 + 2;

int t, n, l, r, now;
char s[N];

void firstchk() {
    while(l < r && s[l] != s[r]) {
        if(s[l] == now)
            l++;
        else
            r--;
        now ^= 1;
    }
    if(l == r && s[l] == now)
        l++;
}

int chkl(int now) {
    for (int i = l; i <= r; i++) {
        if(now != s[i])
            return i;
        now ^= 1;
    }
    return -1;
}

int chkr(int now) {
    for (int i = r; i >= l; i--) {
        if(now != s[i])
            return i;
        now ^= 1;
    }
    return -1;
}

int main() {
    scanf("%d", &t);
    while(t--) {
        now = 0;
        scanf("%d%s", &n, s + 1);
        for (int i = 1; i <= n; i++)
            s[i] &= 1;
        l = 1, r = n;
        firstchk();
        if(l > r) {
            puts("-1");
            continue;
        }
        if(s[l] != now) {
            printf("%d\n", now ^ 1);
            continue;
        }
        int lpos = chkl(now);
        int rpos = chkr(now);
        if(lpos != -1 && s[lpos] == now || rpos != -1 && s[rpos] == now)
            printf("%d\n", now);
        else if(rpos + 1 == lpos || lpos == -1)
            puts("-1");
        else
            printf("%d\n", s[lpos]);
    }
    return 0;
}

1436 Nested String

题目描述:
Given two strings T 1 T_1 T1 and T 2 T_2 T2, a string X X X is T T T-nested if and only if X X X can be represented as the string obtained by inserting T 2 T_2 T2 at a position in T 1 T_1 T1. For example, if T 1 = abcd T_1=\texttt{abcd} T1=abcd and T 2 = ef T_2=\texttt{ef} T2=ef, then efabcd \texttt{efabcd} efabcd, aefbcd \texttt{aefbcd} aefbcd and abcdef \texttt{abcdef} abcdef are all T T T-nested strings.

Given strings S S S, T 1 T_1 T1, and T 2 T_2 T2, your task is to compute the count of distinct T T T-nested substrings in S S S. Two nested substrings are considered distinct if they either occur at different positions in S S S, or [b]the insert positions of T 2 T_2 T2 in T 1 T_1 T1 are different[/b]. A substring of S S S means a continuous sequence of characters from string S S S.

输入:

Ensure to use cin/cout and disable synchronization with stdio to avoid unexpected TLE verdict.

The first line contains a single integer T T T ( 1 ≤ T ≤ 20 1\le T\le 20 1T20), denoting the number of test cases.

The first line of each test case contains two strings T 1 T_1 T1 and T 2 T_2 T2 ( ∣ T 1 ∣ + ∣ T 2 ∣ ≤ ∣ S ∣ |T_1|+|T_2|\le |S| T1+T2S) separated by a single space.

The second line of each test case contains a single string S S S ( ∣ S ∣ ≤ 1 0 7 |S|\le 10^7 S107).

It is guaranteed that S S S, T 1 T_1 T1, and T 2 T_2 T2 all consist only of lowercase letters and ∑ ∣ S ∣ ≤ 2 × 1 0 7 \sum |S|\le 2\times 10^7 S2×107. Here, ∣ S ∣ |S| S means the length of string S S S.
输出
For each test case, output an integer in a single line representing the number of distinct T T T-nested substrings in S S S.

#pragma comment(linker, "/STACK:1024000000,1024000000")

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

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
#define PB push_back
#define fi first
#define se second
#define MP make_pair
const int oo = 1000000000;
const int P = 1000000007;
const int V = 10000100;

void e_kmp(char *s,char *t,int *has,int *e_has)
{
	int sp,p,mx,tn;
	for(sp=p=mx=0;s[p]>0;p++)
	{
		if(mx==p||p+e_has[p-sp]>=mx )
		{
			for(tn=mx-p;s[mx]==t[tn];tn++)mx++;
			has[sp=p]=mx-p;
			if(mx==p)sp=++mx;
		}
		else has[p]=e_has[p-sp];
	}
}

char t1[V], t2[V], s[V], rs[V], rt[V];
int t1_has[V], t2_has[V], s1_has[V], s2_has[V], rt_has[V], rs_has[V];
int sum[V], _;
int main() {
    scanf("%d", &_);
    while (_--) {
        scanf("%s%s%s", t1, t2, s);
        int l1 = strlen(t1);
        int l2 = strlen(t2);
        int n = strlen(s);
        t1[l1] = t2[l2] = -1;
        for (int i = 0; i < l1; ++i) rt[i] = t1[l1 - i -  1]; rt[l1] = -1;
        for (int i = 0; i < n; ++i) rs[i] = s[n - i - 1]; rs[n] = 0;
        t1_has[0] = l1;
        e_kmp(t1+1,t1,t1_has+1,t1_has);
        e_kmp(s,t1,s1_has,t1_has);
        t2_has[0] = l2;
        e_kmp(t2+1,t2,t2_has+1,t2_has);
        e_kmp(s,t2,s2_has,t2_has);
        rt_has[0] = l1;
        e_kmp(rt+1,rt,rt_has+1,rt_has);
        e_kmp(rs,rt,rs_has,rt_has);
        sum[0] = 0;
        for (int i = 0; i < n; ++i) {
            sum[i + 1] = sum[i];
            if (s2_has[i] >= l2) sum[i + 1]++;
        }
        LL ans = 0;
        for (int i = 0; i + l1 + l2 <= n; ++i) {
            int R = s1_has[i] + i;
            int L = i + l1 - rs_has[n - i - l1 - l2];
            if (R >= L) ans += sum[R + 1] - sum[L];
        }
        printf("%lld\n", ans);
    }
    return 0;
}

/*
3
abab ab
abababab
ab a
aaabbaabaa
aba ab
ababaabbabaab

*/

1437 Solubility

题目描述:
In the thriving city, various industries are fueled by the extensive utilization of different liquids. The metropolis houses n n n unique types of liquids, each with specific characteristics and applications ranging from energy to pharmaceuticals.

The Center for Chemical and Physical Combinations (CCPC) plays a pivotal role in researching and categorizing these liquids. A crucial part of their research focuses on understanding the miscibility relations among the liquids. They have identified m m m pairs of miscibility relations, each pair representing two types of liquids that are miscible (mutually soluble).

However, miscibility is not always a straightforward property. It exhibits a transitive relation, meaning if liquid type A A A is miscible with type B B B, and type B B B is miscible with type C C C, then type A A A will also be miscible with type C C C.

Whether developing a new kind of fuel or a groundbreaking medical serum, the right combination of liquids is paramount. An incorrect mixture could lead to immiscible components, which could be ineffective or even dangerous. Therefore, if it is not possible to deduce that two types of liquids are miscible based on the given miscibility relations and their transitivity, then those two types of liquids are considered immiscible.

The industries often require the creation of substances involving a specific set of k k k types of liquids, all of which must be miscible. Your role as a computational scientist at CCPC is to develop an algorithm that will efficiently determine if a given set of k k k types of liquids are miscible. Specifically, for any two distinct types of liquids within this set of k k k types, if they are all miscible with each other, then the k k k types of liquids are considered to be miscible.

输入:
The first line contains an integer T T T ( 1 ≤ T ≤ 20 1 \leq T \leq 20 1T20), representing the number of test cases.

The first line of each test case contains two integers n n n and m m m ( 1 ≤ n , m ≤ 1 0 5 1 \leq n,m \leq 10^5 1n,m105), representing the total number of liquids and the number of solubility relations, respectively.

Each of the next m m m lines contains two integers u u u and v v v ( 1 ≤ u , v ≤ n 1 \leq u,v \leq n 1u,vn, u ≠ v u \neq v u=v), where u u u and v v v represent the types of two liquids that are mutually soluble.

The following line contains a single integer k k k ( 1 ≤ k ≤ n 1 \leq k \leq n 1kn), indicating the number of liquids being considered.

The last line of each test case includes k k k different integers within [ 1 , n ] [1,n] [1,n], each denoting a type of liquid

输出
For each test case, output a single line containing either YES \texttt{YES} YES if all k k k types of liquids are mutually soluble, or NO \texttt{NO} NO if they are not.

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int N=1e5+10; 
int r[N],dist[N];
int t,n,m;
vector<int>val[N];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
void bfs(int x)
{
	queue<int>q;
	memset(dist,-1,sizeof dist);
	q.push(x);
	dist[x]=1;
	
	while(q.size())
	{
		int now=q.front();
		q.pop();
		
		for(int i=0;i<val[now].size();i++)
		{
			int p=val[now][i];
			if(p>=1&&p<=n&&dist[p]==-1)
			{
				dist[p]=dist[now]+1;
				q.push(p);
			}
		}
	}
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);


	cin>>t;
	while(t--)
	{
		int u,v,k;
		cin>>n>>m;		
		memset(val,0,sizeof val);
		while(m--)
		{
			cin>>u>>v;
			
			val[u].push_back(v);
			val[v].push_back(u);
		}
		cin>>k;
		for(int i=1;i<=k;i++)
			cin>>r[i];
		bfs(r[1]);
		int flag=0;
		for(int i=1;i<=k;i++)
		{
			if(dist[r[i]]==-1)
			{
				flag=1;
				break;
			} 
		}
		if(flag) cout<<"NO"<<endl;
		else cout<<"YES"<<endl;		
	}
	return 0;
}

1438 Expectation of Rank

题目描述:
Let p p p be a prime number and F p \mathbb{F}_p Fp be the finite field with order p p p. Suppose A A A is a square matrix of order n n n and each of its entry is a random variable that uniformly distributed on F p \mathbb{F}_p Fp. Please calculate the expectation of the rank of A A A, i.e., E [ r a n k ( A ) ] \mathbb{E}[\mathrm{rank}(A)] E[rank(A)].

In mathematics, a finite field, also known as a Galois field, is a set that contains a finite number of elements. These elements follow the operations of multiplication, addition, subtraction, and division, all of which satisfy the basic rules of arithmetic. The most common examples of finite fields are given by the integers mod p p p when p p p is a prime number.

When we say F p \mathbb{F}_p Fp is a finite field with order p p p, it means that F p \mathbb{F}_p Fp contains exactly p p p distinct elements, with p p p being a prime number. The elements of F p \mathbb{F}_p Fp are the integers 0 , 1 , 2 , . . . , p − 1 0, 1, 2, ..., p-1 0,1,2,...,p1, and the operations of the field are performed modulo p p p. For instance, if p = 5 p=5 p=5, then F 5 \mathbb{F}_5 F5 is the set { 0 , 1 , 2 , 3 , 4 } \{0, 1, 2, 3, 4\} {0,1,2,3,4}, and in this field, 2 + 3 = 0 2+3=0 2+3=0 and 4 × 4 = 1 4 \times 4=1 4×4=1.

输入:
The first line of the input contains an integer T T T ( 1 ≤ T ≤ 50 1 \leq T \leq 50 1T50), denoting the number of test cases.

Each of the following T T T lines contains two integers n , p n, p n,p ( 1 ≤ n ≤ 5000 1 \leq n \leq 5000 1n5000, 2 ≤ p ≤ 1 0 9 2 \leq p \leq 10^9 2p109), denoting the order of the square matrix A A A and the prime number p p p.

It’s guaranteed that the sum of n n n in all test cases will not exceed 5000 5000 5000.

输出
For each test case, output the expectation of the rank of A A A. You should output the answers modulo 1 0 9 + 7 10^9+7 109+7. That is, if the answer is P Q \frac{P}{Q} QP, you should output P ⋅ Q − 1   m o d   1 0 9 + 7 P\cdot Q^{-1}\bmod 10^9+7 PQ1mod109+7, where Q − 1 Q^{-1} Q1 denotes the multiplicative inverse of Q Q Q modulo 1 0 9 + 7 10^9+7 109+7. It can be proved that the answer can always be expressed in this form.

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int P = 1000000007;

typedef vector<int> vi;
typedef vector<vi> mat;

int add(int a, int b) { int r = a + b; return r < P ? r : r - P; }
int sub(int a, int b) { int r = a - b; return r < 0 ? r + P : r; }
int mul(int a, int b) { return 1ll * a * b % P; }
int qpm(int a, int b) {
    int r = 1;
    do if (b & 1) r = mul(r, a);
    while (a = mul(a, a), b >>= 1);
    return r;
}
int inv(int x) { return qpm(x, P - 2); }

int solve(int n, int p) {
    vector<int> pw(n + 1, 1);
    for (int i = 1; i <= n; ++i) {
        pw[i] = mul(pw[i - 1], p);
    }
    vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
    dp[0][0] = 1;
    for (int i = 1; i <= n; ++i) {
        dp[i][0] = 1;
        for (int j = 1; j <= n; ++j)
            dp[i][j] = add(mul(dp[i - 1][j - 1], sub(pw[n], pw[j - 1])), mul(dp[i - 1][j], pw[j]));
    }
    int sum = 0;
    for (int i = 0; i <= n; ++i)
        sum = add(sum, mul(i, dp[n][i]));
    return mul(sum, inv(qpm(pw[n], n)));
}

int main(void) {
    int T;
    cin >> T;
    int n, p;
    while (T--) {
        cin >> n >> p;
        cout << solve(n, p) << endl;
    }
    return 0;
}

1439 Diagonal Fancy

题目描述:
Given a matrix A A A with n n n rows and m m m columns, your objective is to compute the total number of continuous sub-square matrices B B B that are [b]diagonal fancy[/b].

A square matrix B B B is designated as diagonal fancy if it satisfies the subsequent criteria:

  • For any indices i 1 i_1 i1, j 1 j_1 j1, i 2 i_2 i2, and j 2 j_2 j2, if i 1 − j 1 = i 2 − j 2 i_1 - j_1 = i_2 - j_2 i1j1=i2j2, then B i 1 , j 1 = B i 2 , j 2 B_{i_1,j_1} = B_{i_2,j_2} Bi1,j1=Bi2,j2.
  • For any indices i 1 i_1 i1, j 1 j_1 j1, i 2 i_2 i2, and j 2 j_2 j2, if i 1 − j 1 ≠ i 2 − j 2 i_1 - j_1 \neq i_2 - j_2 i1j1=i2j2, then B i 1 , j 1 ≠ B i 2 , j 2 B_{i_1,j_1} \neq B_{i_2,j_2} Bi1,j1=Bi2,j2.
Here, $B_{i,j}$ signifies the element located at the $i$-th row and $j$-th column of matrix $B$. A continuous sub-square matrix from matrix $A$ with $n$ rows and $n$ columns is defined as the matrix derived from $A$ by selecting continuous $n$ rows and continuous $n$ columns.

输入:
Ensure to use cin/cout and disable synchronization with stdio to avoid unexpected TLE verdict.

The input consists of multiple test cases. The first line of the input contains an integer T T T ( 1 ≤ T ≤ 100 1 \leq T \leq 100 1T100), which represents the number of test cases.

The first line of each test case contains two integers n n n and m m m ( 1 ≤ n , m ≤ 1000 1 \leq n, m \leq 1000 1n,m1000), representing the number of rows and columns in the matrix A A A.

Each of the next n n n lines contains m m m space-separated integers A i , 1 , A i , 2 , … , A i , m A_{i,1}, A_{i,2}, \ldots, A_{i,m} Ai,1,Ai,2,,Ai,m ( 1 ≤ A i , j ≤ n × m 1 \leq A_{i,j} \leq n \times m 1Ai,jn×m), representing the elements of the matrix A A A for that particular test case.

It is guaranteed that ∑ n × m ≤ 1 0 7 \sum n\times m\le 10^7 n×m107 over all test cases.

输出
For each test case, output a single integer in a single line, which represents the count of continuous sub-square matrices in matrix A A A that are diagonal fancy.

#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1001;

int t, n, m, a[N][N], f[N][N], g[N] = {1};

bool vis[N * N];

int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                scanf("%d", &a[i][j]);
        for (int i = 1; i <= n; i++)
            f[i][m] = 1;
        for (int j = 1; j <= m; j++)
            f[n][j] = 1;
        for (int i = n - 1; i > 0; i--)
            for (int j = m - 1; j > 0; j--) {
                if(a[i][j] == a[i + 1][j + 1])
                    f[i][j] = min(min(f[i + 1][j], f[i][j + 1]), f[i + 1][j + 1]) + 1;
                else
                    f[i][j] = 1;
            }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                g[j] = g[j - 1] - 1;
                while(g[j] < f[i][j] && !vis[a[i][j + g[j]]] && !vis[a[i + g[j]][j]] && (!g[j] || a[i][j + g[j]] != a[i + g[j]][j])) {
                    vis[a[i][j + g[j]]] = true;
                    vis[a[i + g[j]][j]] = true;
                    g[j]++;
                }
                ans += g[j];
                vis[a[i + g[j] - 1][j]] = false;
                if(g[j] > 1)
                    vis[a[i + g[j] - 2][j]] = false;
            }
        }
        printf("%d\n", ans);
    }
}

1440 Rikka with Square Numbers

题目描述:
Rikka struggles with math. Observing this, Yuta decides to help her improve by assigning some math practice tasks. Here is one such task.

The task requires transforming one integer, a a a, into another, b b b, where a ≠ b a \neq b a=b. In a single operation, Rikka can either add a positive square number to a a a, or subtract a positive square number from a a a. The goal is to convert a a a into b b b by executing the least number of operations.

A square number is an integer that is the product of some integer with itself. For example, 1 1 1, 4 4 4, 9 9 9, and 16 16 16 are square numbers, as they are the squares of 1 1 1, 2 2 2, 3 3 3, and 4 4 4, respectively.

The problem might seem complex for Rikka. Can you assist Rikka in solving this?

输入:
The first line contains one integer T T T ( 1 ≤ T ≤ 1 0 3 1\le T\le 10^3 1T103), indicating the number of test cases.

For each test case, the only line contains two integers a , b a,b a,b ( 1 ≤ a , b ≤ 1 0 9 1\le a,b\le 10^9 1a,b109, a ≠ b a\neq b a=b).

输出
For each test case, output a single line containing one integer, indicating the minimum number of operations required.

#include <cmath>
#include <cstdio>
#include <algorithm>

bool isSqr(int x)
{
	int r = std::sqrt(x);
	return r * r == x;
}

int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		int a, b; scanf("%d %d", &a, &b);
		int d = std::abs(a - b);
		if (isSqr(d))
			puts("1");
		else if (d % 2 == 1 || d % 4 == 0)
			puts("2");
		else
		{
			bool f = false;
			for (int i = 1; i * i <= d && !f; i++)
				f = isSqr(d - i * i);
			puts(f ? "2" : "3");
		}
	}
	return 0;
}

1441 买爱心气球

题目描述:
Alice和Bob是一对竞技编程选手,他们路过了一家气球店,发现有m个大爱心气球和n个小爱心气球。他们决定玩一个游戏,游戏规则如下:

1.Alice先手拿球,两人轮流进行。 2.每个人在自己的回合只能选择一种类型的气球。 3.对于大爱心气球,每次拿取可以选择取5个、2个或1个。4.对于小爱心气球,每次拿取可以选择任意数量(不含0个)。
游戏终止的条件是当所有的气球都被拿取完毕,最后一个球被拿取的人即为获胜者。 假设两人都足够聪明并采取最优策略,请问谁将获胜?

输入:
本题包含多组数据
第一行包含一个正整数T( 1≤T≤1e5),代表测试用例的组数。
对于每组数据:
输入一行包含两个正整数m , n (0≤n, m ≤1e9)。
数据保证 m和 n不同时为0

输出
对于每组数据:
输出一行一个字符串,如果 Alice获胜,输出"Alice"
否则如果Bob获胜,输出"Bob"”(输出不含引号)。

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

void Solve() {
    int n, m;
    cin >> m >> n;
    cout << (n == m % 3 ? "Bob" : "Alice") << '\n';
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    cin >> tt;
    while (tt--) Solve();

    return 0;
}

1442 亚托莉 -我挚爱的时光

题目描述:
亚托莉,-我挚爱的时光-
亚托莉自身机器可能有出了一点小故障,希望你能帮助她解决这个问题~
亚托莉内部的操作系统的是Linux操作系统,不同于Windows 操作系统。在大多数情况下,Linux操作系统一般是通过一些包管理器来安装软件的,以下是一些linux命令((请注意,这些命只是在本题目中有效,其他的有可能不一样哦~)。
1.安装xxx这款软件: sudo pacman -s xxx;
⒉.卸载xxx这款软件,但是不清除这个软件的个人数据: pacman -R xXX;
3.卸载xxx这款软件,并且一并清除这款软件的个人数据:pacman -Rscn xxX;
4.删库跑路: sudo rm -rf /*(-请不要在自己的linux电脑上尝试这条命令哦~)

同时,你需要回答亚托莉问你的几个问题,(后面是提问的形式)
1.亚托莉安装了xxx这款软件了么? ∶1 XXX
2.亚托莉有这款xxx软件的个人数据么? ∶2 XXX
如果是的话,请回答yes,如果没有,请回答no,
注意事项:
1.当软件安装之后,就会有个人数据产生。
⒉.请注意,亚托莉不喜欢删库跑路,如果是含有删库跑路的命名,亚托莉就不跟你玩了,请输出wuwuwu,并且不再回答后面的问题,强制退出。

输入:
第一行有一个数字 n,表示有一共有n 个指令或者问题,(问题和指令加起来有n 个 )。
第2行到n+1行,每一行是一个问题或者是一个命令。
其中 1≤n ≤1e6
保证输入没有错误,删除软件之前一定会有安装。软件不会被安装多次,而且软件名称不会含有空格。

输出
1.如果是命令,请执行。
2.如果是问题,请根据问题回答,如果是正确的,请回答 yes,如果是错误的,请回答no,
3.如果含有命令为 sudo rm -rf /*,请输出 wuwuwu,并且不在回答后面的问题,强制退出。(输出不含双引号)

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

void Solve() {
    int n;
    cin >> n;

    map<string, array<int, 2>> mp;

    for (int i = 1; i <= n; i++) {
        string op, tmp, info;
        cin >> op;
        if (op == "sudo") {
            cin >> tmp; cin >> tmp; cin >> info;
            if (info == "/*") {
                cout << "wuwuwu" << '\n';
                return;
            }
            mp[info] = {1, 1};
        } else if (op == "pacman") {
            cin >> tmp >> info;
            if (tmp == "-R") {
                mp[info] = {0, 1};
            } else {
                mp[info] = {0, 0};
            }
        } else if (op == "1") {
            cin >> info;
            if (mp.count(info) && mp[info][0]) {
                cout << "yes" << '\n';
            } else {
                cout << "no" << '\n';
            }
        } else if (op == "2") {
            cin >> info;
            if (mp.count(info) && mp[info][1]) {
                cout << "yes" << '\n';
            } else {
                cout << "no" << '\n';
            }
        }
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    // cin >> tt;
    while (tt--) Solve();

    return 0;
}

1443 数位DP

题目描述:
给定一个正整数n,你可以对n进行任意次(包括零次)如下操作:

选择n上的某一数位,将其删去,剩下的左右部分合并。例如123,你可以选择删去第二位2,得到新数13。在对n进行操作后,请问有多少种不同的n,使得n不是3的倍数?

由于结果可能非常大,请输出对1000000007取模的结果。

输入:
第一行包含一个正整数n (1≤n ≤ 1e200000)
数据保证最初生成的n不含前导0。

输出
输出一行,代表对1000000007取模后的结果。

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

constexpr int P = 1E9 + 7;

void Solve() {
    string s;
    cin >> s;
    int n = s.size();
    s = " " + s;

    vector<array<int, 10>> nxt(n + 1, array<int, 10>{});
    for (int i = 0; i < 10; i++) {
        nxt[n][i] = n + 1;
    }
    for (int i = n; i >= 1; i--) {
        for (int j = 0; j < 10; j++) {
            nxt[i - 1][j] = nxt[i][j];
        }
        nxt[i - 1][s[i] - '0'] = i;
    }

    vector<array<ll, 3>> dp(n + 1, array<ll, 3>{});
    dp[0][0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 10; j++) {
            if (nxt[i][j] == n + 1 || (!j && !i)) {
                continue;
            }
            for (int k = 0; k < 3; k++) {
                int t = nxt[i][j];
                dp[t][(k + j) % 3] = (dp[t][(k + j) % 3] + dp[i][k]) % P;
            }
        }
    }

    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = (ans + dp[i][1] + dp[i][2]) % P;
    }

    cout << ans << '\n';
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    // cin >> tt;
    while (tt--) Solve();

    return 0;
}

1444 01分数规划

题目描述:
给定一个字符串s,仅含0,1,?三种字符,你必须将所有 ?替换为1或0。

定义s的美好值为将所有?进行替换后,s的最长连续1或0的子串的长度。请你进行所有替换后,使得字符串s的美好值最大,请输出这个美好值。

输入:
本题包含多组数据
第一行包含一个正整数T(1<T≤2 ×1e5),表示测试数据组数。
对于每组数据:
第一行包含一个正整数n (1 ≤n≤1 x 1e6),表示字符串 s 的长度|s|。
接下来一行一个字符串 s,描述如题目所示,si∈ { 1, 0, ?} (1≤i≤n)。
数据保证 ∑ i = 0 n \sum_{i=0}^n i=0n |s| ≤ \leq 1x1e6

输出
对于每组数据:
输出一行一个整数,代表字符串s 的最大美好值。

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

void Solve() {
    int n;
    cin >> n;

    string s;
    cin >> s;

    int ans = 0;

    auto cal = [&](const string& s, char op) {
        int cur = 0, mx = 0;
        for (auto x : s) {
            if (x == op) {
                cur++;
            } else {
                mx = max(mx, cur);
                cur = 0;
            }
        }
        mx = max(mx, cur);
        return mx;
    };

    auto a = s;
    for (auto& x : a) {
        if (x == '?') {
            x = '1';
        }
    }
    ans = max(ans, cal(a, '1'));

    auto b = s;
    for (auto& x : b) {
        if (x == '?') {
            x = '0';
        }
    }
    ans = max(ans, cal(b, '0'));

    cout << ans << '\n';
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    cin >> tt;
    while (tt--) Solve();

    return 0;
}

1445 换根DP

题目描述:
给定一棵n个节点的无根树,其中边权只有1或2两种。
现在定义u →v两点之间的距离w (u,v)为两点间简单路径上所有边权的最大公约数。令f(t)表示为节点t到树上其他节点的距离之和。
求min(f(1),f(2),. . . ,f(n))。

输入:
第一行包含一个正整数n(1 ≤n≤1e5),代表这棵树的节点数量。
接下来n-1行,每行三个正整数 u, v, w (1≤u,v≤n,1≤w≤2),代表u和v之间有一条权值为w的无向边。

输出
输出一行一个正整数,代表min(f(1),f(2),f(3)…f(n))。

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

struct DSU {
    vector<int> f, siz;
    DSU(int n) : f(n + 1), siz(n + 1, 1) {
        siz[0] = 0;
        iota(f.begin(), f.end(), 0);
    }
    bool same(int x, int y) {
        return find(x) == find(y);
    }
    int find(int x) {
        while (x != f[x]) x = f[x] = f[f[x]];
        return x;
    }
    bool merge(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return 0;
        siz[x] += siz[y];
        f[y] = x;
        return 1;
    }
    int size(int x) {
        return siz[find(x)];
    }
};

void Solve() {
    int n;
    cin >> n;

    DSU dsu(n);

    for (int i = 1; i < n; i++) {
        int u, v, w;
        cin >> u >> v >> w;

        if (w == 2) {
            dsu.merge(u, v);
        }
    }

    int mn_blk = 1e9;

    for (int i = 1; i <= n; i++) {
        mn_blk = min(mn_blk, dsu.size(i));
    }
    cout << (n - mn_blk) + 2 * (mn_blk - 1) << '\n';
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    // cin >> tt;
    while (tt--) Solve();

    return 0;
}

1446

题目描述:

输入:

输出


1447 Kruskal

题目描述:
给定一张n个点的无向完全图,其中两点之间的路径边权为两点编号的按位与(编号为(1,2…,n)),即u (u, v)=u&v (1 ≤u, v≤n),求该图最小生成树的边权和。

输入:
本题包含多组数据
第一行包含一个正整数T(1≤T≤2×1e5),代表测试用例的组数。
对于每组数据:
第一行输入一个正整数n (2≤n<1e9),代表该完全图的节点个数。

输出
对于每组数据:
输出一行一个整数,代表该完全图最小生成树的边权和。

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

void Solve() {
    int n;
    cin >> n;
    n++;

    cout << ((n & -n) == n ? 1 : 0) << '\n';
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    cin >> tt;
    while (tt--) Solve();

    return 0;
}

1448 三维偏序

题目描述:
给定一个由n个正整数组成的序列a,你可以通过j一i个花费交换a;, aj(j > i)两个元素。


我们定义一个位置i是好的,当且仅当ai不与其他元素发生交换的前提下,使得a1,…,ai-1≤ai,即位置1~i-1上的元素均小于等于ai。请注意,满足上述要求并不需要1~i-1中元素有序,只需要满足与ai的相对大小关系即可。

对于所有的 i ∈ {1,2,... , n},分别求出使位置 i 是好的所需要的最小花费是多少。如果怎么操作都无法使 i 位置是好的,则输出一1。 对于每个i,进行的操作是相互独立的,并没有真正修改原数组的位置。

输入:
输入一行一个正整数n(1 ≤n ≤1e5),代表序列a的长度。
接下来一行n个正整数a1, a2,…, an(0 ≤ai≤1e9),代表序列a 的元素。

输出
输出一行n 个整数,第 i 个整数代表使得 i 位置是好的所需要的最小花费,如果怎么操作都无法使 i 位置是好的,输出—1。

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

struct info {
    ll sum;
    int cnt;

    info operator+(const info& it) const {
        return {sum + it.sum, cnt + it.cnt};
    }
};

template <typename T>
struct Fenwick {
    int n;
    vector<T> a;
    Fenwick(int n) : n(n), a(n + 10) {}
    void add(int x, T v) {
        for (int i = x; i <= n; i += i & -i) {
            a[i] = a[i] + v;
        }
    }
    T sum(int x) {
        T ans = {0, 0};
        for (int i = x; i; i -= i & -i) {
            ans = ans + a[i];
        }
        return ans;
    }
    T rangeSum(int l, int r) {
        if (l <= 1) return sum(r);
        return sum(r) - sum(l - 1);
    }
    ll kth(int k) {
        int x = 0;
        ll ret = 0;
        for (int i = 1 << __lg(n); i; i /= 2) {
            if (x + i <= n && k >= a[x + i].cnt) {
                x += i;
                k -= a[x].cnt;
                ret += a[x].sum;
            }
        }
        return (k ? -1 : ret);
    }
};

void Solve() {
    int n;
    cin >> n;

    vector<array<int, 2>> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i][0];
        a[i][1] = i;
    }

    sort(a.begin() + 1, a.end());

    vector<ll> ans(n + 1);
    Fenwick<info> fen(n + 1);

    for (int i = 1, j = 1; i <= n; i++) {
        while (j <= n && a[j][0] <= a[i][0]) {
            fen.add(a[j][1], {a[j][1], 1});
            j++;
        }

        /*鏍戜笂浜屽垎
        ll v1 = fen.kth(a[i][1]);*/

        auto search = [&](int x) {
            if (fen.sum(n).cnt < x) {
                return -1ll;
            }

            int l = 0, r = n;
            while (l < r) {
                int mid = l + r >> 1;
                if (fen.sum(mid).cnt < x) {
                    l = mid + 1;
                } else {
                    r = mid;
                }
            }

            return fen.sum(l).sum;
        };

        ll v1 = search(a[i][1]);

        if (v1 != -1) {
            v1 -= 1ll * a[i][1] * (a[i][1] + 1) / 2;
        }
        ans[a[i][1]] = v1;
    }

    for (int i = 1; i <= n; i++) {
        cout << ans[i] << " \n"[i == n];
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tt = 1;
    // cin >> tt;
    while (tt--) Solve();

    return 0;
}

1449 双指针

题目描述:
给定一个数组α和数组b,两个数组的长度都为n,请选择分别两个下标i,j,且 i,j满足条件1<i<j≤n,求有多少对i,j满足ai× aj = bi x bj。

输入:
本题包含多组数据
第一行包含一个正整数T(1≤T≤1 ×1e5)。
对于每组数据:
第一行包含一个正整数n(1 ≤n ≤2 ×1e5) 。
接下来2行
第1行包含n个整数a1, a2, a3.….an(1 ≤ai≤2×1e5) 。
第2行包含n个整数b1, b2, b3…bn(1 ≤bi≤2×1e5) 。
∑ i = 1 T \sum_{i=1}^T i=1T n≤2×1e5

输出
对于每组数据:
输出一行表示有多少对i,j 满足ai× aj = bj x bi 。

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

using i64 = long long;

void solve() {
    int n;
    cin >> n;
    vector<int> a(n), b(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> b[i];
    }
    map<array<int, 2>, int> cnt;
    i64 ans = 0;
    for (int i = 0; i < n; ++i) {
        int _gcd = gcd(a[i], b[i]);
        ans += cnt[{b[i] / _gcd, a[i] / _gcd}];
        ++cnt[{a[i] / _gcd, b[i] / _gcd}];
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

1450 树上DP

题目描述:
给定一棵树,根节点为1,每个节点都有权值,可以交换任意次任意相邻节点的权值,定义一棵树的美丽值为该树的所有子树的节点的权值和的总和,求美丽值最大值为多少?

输入:
本题包含多组数据
第一行包含一个正整数T(1≤T≤1× 1e5)。
对于每组数据:
第一行包含一个正整数n(1 ≤n≤2 ×1e5) 。
接下来n-1行,每行包含两个整数u,v (1 ≤u,u≤n),表示 u,v之间有一条无向边。
最后一行包含 n 个正整数a1, a2, a3,…, an (1≤ai≤1×1e5),表示每个节点的权值。
∑ i = 1 T \sum_{i=1}^T i=1T n≤2×105

输出
对于每组数据:
输出一行表示树的最大美丽值

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

using i64 = long long;

void solve() {
    int n;
    cin >> n;
    vector<vector<int>> g(n);
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        --u, --v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    vector<int> dep(n);
    function<void(int, int)> dfs = [&](int u, int f) {
        for (auto &v : g[u]) {
            if (v == f) continue;
            dep[v] = dep[u] + 1;
            dfs(v, u);
        }
    };
    dfs(0, -1);
    sort(a.begin(), a.end());
    sort(dep.begin(), dep.end());
    i64 ans = 0;
    for (int i = 0; i < n; ++i) {
        ans += 1ll * a[i] * (dep[i] + 1);
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

1451 01BFS

题目描述:
给定一个n x m的矩阵G,每个单元有权值Gij,请选定其中一个单元为起点,再选定一个起始方向(上下左右),可以多次跳到该方向上权值严格大于当前单元权值的单元上,如果最开始选择的为左右方向,可换一次方向(上或下)继续跳,如果最开始选择的为上下方向,可换一次方向(左或右)继续跳,也可以不换方向,求最多能跳多少次?

输入:
本题包含多组数据
第一行包含一个正整数T(1≤T≤1×1e5)。
对于每组数据:
第一行包含两个正整数n, m(1 ≤n x m ≤1 x 1e6) 。接下来 n行,每行包含m个整数(1≤Gi,j ≤1×1e5)。
∑ i = 1 T \sum_{i=1}^T i=1T (n x m)≤1 x1e6

输出
对于每组数据:
输出一行一个数表示最多能跳多少次。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve() {
    int n, m;
    cin >> n >> m;
    vector a(n, vector<int>(m));
    for (auto& i : a)
        for (auto& j : i) cin >> j;

    vector len(n, vector<array<int, 8>>(m));
    array<array<int, 2>, 4> start{0, 0, 0, m - 1, n - 1, 0, 0, 0};

    for (int direc = 0; direc < 8; direc++) {
        int base = direc & 1 ? -1 : 1;

        auto dp = [&](auto& dp, int i, int j) -> void {
            auto pos = lower_bound(dp.begin(), dp.end(), base * a[i][j]);
            len[i][j][direc] = pos - dp.begin() + 1;
            if (pos == dp.end()) dp.push_back(base * a[i][j]);
            else *pos = base * a[i][j];
        };

        auto [x, y] = start[direc / 2];

        if (direc / 2 == 0)
            for (int j = y; j < m; j++) {
                vector<int> _dp;
                for (int i = x; i < n; i++) dp(_dp, i, j);
            }
        else if (direc / 2 == 1)
            for (int i = x; i < n; i++) {
                vector<int> _dp;
                for (int j = y; j >= 0; j--) dp(_dp, i, j);
            }
        else if (direc / 2 == 2)
            for (int j = y; j < m; j++) {
                vector<int> _dp;
                for (int i = x; i >= 0; i--) dp(_dp, i, j);
            }
        else if (direc / 2 == 3)
            for (int i = x; i < n; i++) {
                vector<int> _dp;
                for (int j = y; j < m; j++) dp(_dp, i, j);
            }
    }

    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (auto& direc : {0, 2, 4, 6}) {
                for (auto& other : {1, 3, 5, 7}) {
                    if (direc + 1 == other) continue;
                    ans = max(len[i][j][direc] + len[i][j][other] - 1, ans);
                }
            }
        }
    }
    cout << ans << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
}

1452 异或与

题目描述:
给你一个长度为n的序列a,请你从中找到两个下标i,j(i≠j),满足ai⊕aj=2×(ai & aj)。其中⊕为按位异或,
异或运算的规则是:
0⊕0=0
0⊕1=1
1⊕0=1
1⊕1=0

& 为按位与,
与运算的规则是:

1 & 1 = 1
1 & 0 = 0
0 & 1 = 1
0 & 0 = 0

输入:
第一行一个正整数n(2≤n ≤1e5)表示数列长度
第二行n个整数a1, a2,…, an (∀ i∈ [1,n],0 ≤ai≤1e18)

输出
输出以空格分隔的两个正整数,表示你找到的下标
如果有多个合法答案,输出任意一个即可
如果没有,输出―1

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(false);

    int n;
    std::cin >> n;
    std::map<int64_t, std::vector<int>> ids;
    std::vector<int64_t> a(n + 1);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        ids[a[i]].push_back(i);
    }

    if (ids.count(0)) {
        if (ids[0].size() >= 2) {
            std::cout << ids[0][0] << " " << ids[0][1] << std::endl;
            return 0;
        }
    }

    for (auto it : ids) {
        int64_t x = it.first;
        int64_t tx = x;
        if (x == 0) continue;
        std::string v1;
        while (x) v1 += (x & 1) + '0', x >>= 1;
        v1 += '0';
        std::string v2;
        for (int i = 0; i + 1 < v1.size(); i++) {
            if (v1[i] == '1') {
                v2 += '1';
                v2 += !(v1[i + 1] - '0') + '0';
                i++;
            } else {
                v2 += '0';
            }
        }
        int64_t y = 0;
        for (int i = v2.size() - 1; i >= 0; i--) {
            y = y * 2 + v2[i] - '0';
        }
        x = tx;
        if (!ids.count(y)) continue;
        if ((x ^ y) == 2ll * (x & y)) {
            std::cout << ids[x][0] << " " << ids[y][0] << std::endl;
            return 0;
        }
    }

    std::cout << "-1\n";
}

1453 扫描线

题目描述:
现有一凸多边形在二维平面上。一水平直线在无穷远处,每时刻以一个单位长度的速度朝着凸多边形的方向移动。t时刻与凸多边形相交,经过了x个时刻与凸多边形相离。你可以任意旋转或平移这个凸多边形,求这条直线与凸多边形相交的最短时间x是多少?

输入:
本题包含多组数据
第一行包含一个正整数T (1<T≤5×1e5)。对于每组数据:
第一行包含一个正整数n (3≤n≤5× 1e4)。
接下来n行,每行包含两个整数x,y (-1e6≤x,y ≤ 1e6),表示凸多边形顶点的坐标,按逆时针顺序给出。
∑ i = 1 T \sum_{i=1}^T i=1T n≤5×1e5

输出
对于每组数据:
输出一行包含一个小数x,表示最短时间(保留两位小数)


#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve() {
    int n;
    cin >> n;
    vector<array<ll, 2>> point(2 * n - 1);
    for (int i = 0; i < n; i++) cin >> point[i][0] >> point[i][1];

    for (int i = n; i < point.size(); i++) point[i] = point[i - n];

    auto cross = [&](int a, int b) {
        return point[a][0] * point[b][1] - point[a][1] * point[b][0];
    };

    auto calc = [&](int a, int b, int c) { return cross(a, b) + cross(b, c) + cross(c, a); };

    auto dis = [&](int a, int b) {
        ll x = point[a][0] - point[b][0], y = point[a][1] - point[b][1];
        return sqrt(x * x + y * y);
    };

    double ans = 1e100;
    for (int i = 0; i < n; i++) {
        int l = i + 2, r = i - 1 + n;
        while (l < r) {
            int mid = (l + r) / 2;
            if (calc(i, i + 1, mid) <= calc(i, i + 1, mid + 1)) l = mid + 1;
            else r = mid;
        }
        ans = min(calc(i, i + 1, l) / dis(i, i + 1), ans);
    }

    cout << fixed << setprecision(2);
    cout << ans << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
}

1454

题目描述:

输入:

输出


  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值