The 2022 ICPC Asia Regionals Online Contest (II) A、B、E、F、G、J、L

42 篇文章 1 订阅

A-Yet Another Remainder

题目

题目描述

There is a positive integer x(1≤x<101000000) in the computer, but now you don’t know it. Since the integer is extremely large, it is represented as a string a 1 a 2 a 3 . . . a n a_{1}a_{2}a_{3}...a_{n} a1a2a3...an, where the integer n denotes the number of digits in x. For example, integer 123 can be represented as a a 1 a_{1} a1=1, a 2 a_{2} a2=2, a 3 a_{3} a3=3.
Now you don’t want to know the exact value of integer x, but the remainder of x when it is divided by another positive integer p. Formally, you should calculate x mod p, where mod means the remainder of the division.
To get information, you can ask computer some questions: Q(l,r,k), ask the sum of the digits from l to r, step by k. Formally, you will get a l + a l + k + a l + 2 k + . . . + a r a_{l}+a_{l+k}+a_{l+2k}+...+a_{r} al+al+k+al+2k+...+ar.
Now you have asked computer some questions in min(100,n) rounds. In the i t h i^{th} ith round, you thrown i questions: in the j t h j^{th} jth question in this round, you ask Q ( j , i × ⌊ n − j i ⌋ + j , i ) Q(j,i \times \lfloor\frac{n-j}{i}\rfloor + j,i) Q(j,i×inj+j,i), where ⌊ x ⌋ \lfloor x\rfloor x means the greatest integer less than or equal to x. In other word, let l be j, let r be i × ⌊ n − j i ⌋ + j i \times \lfloor\frac{n-j}{i}\rfloor + j i×inj+j, you will get a l + a l + i + a l + 2 i + . . . + a r a_{l}+a_{l+i}+a_{l+2i}+...+a_{r} al+al+i+al+2i+...+ar.
Hint: here r means the greatest integer satisfying r=l+k⋅i,k∈R and r≤n.
Finally, you should answer q queries. In each query, you are given a prime number p(with special limit:p=3 or 7≤p≤97), and you should tell computer x mod p as the answer.

输入格式

There are multiple test cases.
The first line contains an integer t(1≤t≤100), the number of test cases.
The first line of each test case is an integer n(1≤n≤10^6), the number of digits of the hidden number.
The following min(100,n) lines are about the questions.
The i t h i^{th} ith line contains i integers b i , 1 , b i , 2 , . . . b i , i ( 0 ≤ b i , j ≤ 1 0 7 ) b_{i,1},b_{i,2},...b_{i,i}(0\le b_{i,j}\le10^7) bi,1,bi,2,...bi,i(0bi,j107), b i , j b_{i,j} bi,j represents the answer of the j t h j^{th} jth question of the i t h i^{th} ith round.
It is guaranteed that there exists a number fits all the answers of the questions.
The next line contains an integer q(1≤q≤10), the number of queries.
Then q line follows, each line contains a prime number p(p=3 or 7≤p≤97), the modulus of the query.

输出格式

For each query, print your answer in a single line.

输入样例

1
9
47
27 20
14 18 15
16 13 11 7
13 12 13 5 4
12 14 11 2 4 4
14 12 8 2 4 4 3
12 9 8 2 4 4 3 5
9 9 8 2 4 4 3 5 3
5
3
7
31
67
97

输出样例

2
1
23
30
87

The hidden number in sample case is 998244353.
In the first round, you get b 1 , 1 = 9 + 9 + 8 + 2 + 4 + 4 + 3 + 5 + 3 = 47 b_{1,1}=9+9+8+2+4+4+3+5+3=47 b1,1=9+9+8+2+4+4+3+5+3=47.
In the second round, you get b 2 , 1 = 9 + 8 + 4 + 3 + 3 = 27 b_{2,1}=9+8+4+3+3=27 b2,1=9+8+4+3+3=27 and b 2 , 2 = 9 + 2 + 4 + 5 = 20 b_{2,2}=9+2+4+5=20 b2,2=9+2+4+5=20.
In the third round, you get b 3 , 1 = 9 + 2 + 3 = 14 b_{3,1}=9+2+3=14 b3,1=9+2+3=14, b 3 , 2 = 9 + 4 + 5 = 18 b_{3,2}=9+4+5=18 b3,2=9+4+5=18 and b 3 , 3 = 8 + 4 + 3 = 15 b_{3,3}=8+4+3=15 b3,3=8+4+3=15.
In the first query, your answer is 998244353 mod 3 = 2.
In the second query, your answer is 998244353 mod 7 = 1.

代码长度限制 16 KB
时间限制 1000 ms
内存限制 128 MB

题解

思路解析

关键公式 欧拉降幂公式
a b ≡ a b   m o d   p − 1 ( m o d   p )   ,   g c d ( a , p ) = 1 a^b\equiv a^{b\space mod\space p-1}(mod\space p)\space ,\space gcd(a,p)=1 abab mod p1(mod p) , gcd(a,p)=1
证明
满足 g c d ( a , p ) = 1 的条件下 a p − 1 ≡ 1 ( m o d   p )   a x ≡ a k ( p − 1 ) + x   m o d   p − 1 ≡ a p − 1 k × a x   m o d   p − 1 ( m o d   p ) a p − 1 k ≡ 1 k ( m o d   p ) a x ≡ a x   m o d   p − 1 ( m o d   p ) 满足gcd(a,p)=1的条件下\\a^{p-1}\equiv 1(mod\space p)\space\\a^{x}\equiv a^{k(p-1)+x\space mod\space p-1}\equiv{a^{p-1}}^{k}\times a^{x\space mod\space p-1}(mod \space p)\\{a^{p-1}}^{k}\equiv 1^k(mod\space p)\\a^{x}\equiv a^{x\space mod \space p-1} (mod\space p) 满足gcd(a,p)=1的条件下ap11(mod p) axak(p1)+x mod p1ap1k×ax mod p1(mod p)ap1k1k(mod p)axax mod p1(mod p)

下面我们将给出的线索中的第i行第j列的表达式表示出来

公式
G i j = ∑ k = 1 n a k [ k ≡ j ( m o d   i ) ] G_{i}^{j}=\sum_{k=1}^{n}a_{k} [k\equiv j(mod\space i)] Gij=k=1nak[kj(mod i)]
表示在1-n中所有与j在i模系下相同的数字和
然后我们利用上面的式子求出来n的表达式
n u m ≡ ∑ j = 1 i ∑ k = 1 n a k × 1 0 ( n − k )   % ( p − 1 )   [ k ≡ j ( m o d   i ) ] ( m o d   p ) num\equiv \sum_{j=1}^{i}\sum_{k=1}^{n}a_{k}\times10^{(n-k)\space \% (p-1)}\space [k\equiv j(mod\space i)](mod\space p) numj=1ik=1nak×10(nk) %(p1) [kj(mod i)](mod p)
我们令i=p-1
n u m ≡ ∑ j = 1 p − 1 ∑ k = 1 n a k × 1 0 ( n − k )   % ( p − 1 )   [ k ≡ j ( m o d   p − 1 ) ] ( m o d   p ) num\equiv \sum_{j=1}^{p-1}\sum_{k=1}^{n}a_{k}\times10^{(n-k)\space \% (p-1)}\space [k\equiv j(mod\space p-1)](mod\space p) numj=1p1k=1nak×10(nk) %(p1) [kj(mod p1)](mod p)
紧接着我们可把n-k等价为n-j
n u m ≡ ∑ j = 1 p − 1 ∑ k = 1 n a k × 1 0 ( n − j )   % ( p − 1 )   [ k ≡ j ( m o d   p − 1 ) ] ( m o d   p )   n u m ≡ ∑ j = 1 p − 1 1 0 ( n − j )   % ( p − 1 ) ∑ k = 1 n a k   [ k ≡ j ( m o d   p − 1 ) ] ( m o d   p )   n u m ≡ ∑ j = 1 p − 1 1 0 ( n − j )   % ( p − 1 ) G p − 1 j ( m o d   p ) num\equiv \sum_{j=1}^{p-1}\sum_{k=1}^{n}a_{k}\times10^{(n-j)\space \% (p-1)}\space [k\equiv j(mod\space p-1)](mod\space p)\\ \space \\ num\equiv \sum_{j=1}^{p-1}10^{(n-j)\space \% (p-1)}\sum_{k=1}^{n}a_{k}\space [k\equiv j(mod\space p-1)](mod\space p)\\ \space \\ num\equiv \sum_{j=1}^{p-1}10^{(n-j)\space \% (p-1)}G_{p-1}^{j}(mod\space p) numj=1p1k=1nak×10(nj) %(p1) [kj(mod p1)](mod p) numj=1p110(nj) %(p1)k=1nak [kj(mod p1)](mod p) numj=1p110(nj) %(p1)Gp1j(mod p)
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
ll prime[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151 };
int main()
{
	ll n = read, m = read;
	ll ans = m;
	for (int i = 0; i < 36; i++)
	{
		if (gcd(prime[i], m) == 1)
		{
			ans += prime[i];
			ll surplus = n - 2;
			if (prime[i] != 2)
			{
				ans += surplus / 2 * 5;
				if (surplus & 1)ans += 2;
			}
			else
			{
				ans += surplus / 2 * 5;
				if (surplus & 1)ans += 3;
			}
			print(ans);
			break;
		}
	}
}

B-Non-decreasing Array

题目

题目描述

You are given a non-decreasing array of integers a 1 , a 2 , . . . , a n a_{1},a_{2},...,a_{n} a1,a2,...,an.In one operation, when the current length of the array is m:

  • Firstly you can choose an index i(1<i<m) and delete a i a_{i} ai (m decrease 1) or you can do nothing,
  • Secondly you can choose an index i(1<i<m) and change a i a_{i} ai to any integer.

You should ensure that the array is non-decreasing after every delete or change.
Now you want to know that after operating k(1≤k≤n) times, when the current length of the array is m, what is the maximum value of ∑ i = 2 m ( a i − a i − 1 ) 2 \sum_{i=2}^{m}(a_{i}-a_{i-1})^2 i=2m(aiai1)2.You need to answer for each k(1≤k≤n), different queries are independent of each other.

输入格式

The first line contains one integer n(3≤n≤100).
The second line contains n integers a 1 , a 2 , . . . , a n ( − 1 0 9 ≤ a i ≤ 1 0 9 ) a_{1},a_{2},...,a_{n}(-10^9\le a_{i}\le 10^9) a1,a2,...,an(109ai109).

输出格式

Output n lines, each of which contains a single integer—the i-th number is for the answer of k=i.

输入样例

5
1 2 3 4 5

输出样例:

10
16
16
16
16

代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB

题解

思路解析

首先我们分析四组数据的关系

1 2 3
1 1 3
1 3 3
1 3

我们很轻松的发现,后面三组正是做了题目描述中的操作之后的结果,我们发现中间两种是进行修改,而最后一组做的是删除操作。
如果我们修改的数值和两端的一致的话,实际上我们就是做了删除的操作。
那么为什么要修改到两端呢?请添加图片描述
横坐标代表的是中间数值的变化值,左移为正。我们会发现这是一个对称抛物线,而在最两侧的结果一致且最大。

所以我们可以制定一个贪心策略是每次执行2*k次删除操作。
但是我们限定了头尾两个数字是无法删除的。
那么我们每个长度中可以存在的数在[0,len-2]中。
这题显然用dp做。
我们可以假定的想一下,如果给你什么条件再结合当前的这一个位置是数字我们可以直接推过来的。因为数据不是特别大我们可以知道最大复杂度应该为O(n4),所以我们可以枚举之前所有情况进行结合取最大值。
因为我们知道我们添加上一个新的数字肯定是比添加前的那个组合的数字是要大一些的。但是不一定随便找一个就是最大,我们需要枚举出,与我结合,能够达到预计剩余量的前状态里的一个最大值。
说这么多,状态转移究竟是怎么回事呢?
在这里插入图片描述
左图两个绿色的代表前面某个状态的首和尾部,我们拼接一个新的串后我们可以得到一个长度为当前所需的一个串,而增加的价值为红色部分,因为橙色部分是不存在的,可以理解成被合并或者被删除了,是前面某个长度的状态与此时的状态下是没有任何意义的,所以忽略,而增加的红色部分的价值就是(VEnd-VSta)2
这里要特别强调的是,我们加上一个新的后我们可以结合之前的最后一个值max(pre,now)而去把橙色部分全部去掉,因此印证了我们这么做的可行性。我们可以得到剩下的里面的剩余某个数量的最优解,因为我们按照这个思路求的是最优解,那之前当然也是了。
其实我们后面是由前面推出的,更像是一个递归问题里求记忆化搜索,这么方向思考以下就可以了。
但是我们现在想要剩余三个的,那么我们添加了一个,所以我们还需要获得前面所有状态里剩两个的最大的值。
至于起始点和终止点的关系,自己模拟一下找找关系就可以了,这里不做过多赘述。
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const ll less_inf = 0x3f3f3f3f;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
#define addval(Lval, Rval) ((Rval - Lval)* (Rval - Lval))
ll dp[105][105];
ll save[105];
int main()
{
	int n = read;
	for (int i = 1; i <= n; i++)save[i] = read;
	dp[2][0] = addval(save[2], save[1]);
	for (int i = 3; i <= n; i++)
	{
		dp[i][0] = addval(save[i], save[1]);
		for (int rest = 1; rest < i - 1; rest++)
			for (int end = rest + 1; end < i; end++)
				dp[i][rest] = max(dp[i][rest], dp[end][rest - 1] + addval(save[end], save[i]));
	}
	for (int i = 1; i <= n; i++)
	{
		out(dp[n][max(n - 2 * i - 2, 0)]);
		puts("");
	}
}

E-An Interesting Sequence

题目

题目描述

You should generate a sequence of positive integers of length n.
Of course,this sequence needs to meet some requirements.

  • ∀ i ∈ [ 1 , n ]   a i > 1 \forall i\in [1,n]\space a_{i} > 1 i[1,n] ai>1
  • ∀ i ∈ [ 2 , n ]   g c d ( a i − 1 , a i ) = 1 \forall i\in [2,n]\space gcd(a_{i-1},a_{i}) = 1 i[2,n] gcd(ai1,ai)=1
  • a 1 = k ( k > 1 ) a_{1}=k(k>1) a1=k(k>1)

gcd(x,y) means the greatest common divisor of x and y.
You need to find the minimum value of ∑ i = 1 n a i {\textstyle \sum_{i=1}^{n}a_{i}} i=1nai.

输入格式

The only line contains two integers n,k
2 ≤ n ≤ 1 0 8 , 2 ≤ k ≤ 1 0 8 2\le n\le10^8,2\le k\le10^8 2n108,2k108

输出格式

One integer — the answer to the problem.

输入样例

2 5

输出样例

7

代码长度限制 16 KB
时间限制 400 ms
内存限制 128 MB

题解

思路解析

由于我们要求gcd(ai-1,ai)=1,所以第二个数字一定是第一个数的最小质数,(贪心策略越小越好)
那么我们也可以轻易知道,质数和另一个质数的gcd=1,而恰巧2,3都是两个最小的gcd,也就是说无论第二个数是多少我们第三个数字不是2就是3,所以奇数的话就出2就可以了,因为2更小,如果是偶数2就不可以了,就需要从3开始,事实上只有第二个数是2的时候我们才从3开始。
所以我们计算出来前两个后求surplus就可以计算出剩余的数字了。
最小的质数怎么求?
换句话说,怎么样让最小的质数一直增加?
那就是包含的最小质数连乘,也就是 ∏ i = 1 ∞ P r i m e [ i ] \prod_{i=1}^{\infty } Prime[i] i=1Prime[i]但是这个数字最大不会超过1e8,所以这个i的最大值也很有限,所以呢,我们其实求十几个质数就可以枚举试一试了。
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
ll prime[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151 };
int main()
{
	ll n = read, m = read;
	ll ans = m;
	for (int i = 0; i < 36; i++)
	{
		if (gcd(prime[i], m) == 1)
		{
			ans += prime[i];
			ll surplus = n - 2;
			if (prime[i] != 2)
			{
				ans += surplus / 2 * 5;
				if (surplus & 1)ans += 2;
			}
			else
			{
				ans += surplus / 2 * 5;
				if (surplus & 1)ans += 3;
			}
			print(ans);
			break;
		}
	}
}

F-Infinity Tree

题目

题目描述

You have a rooted tree with infinite number of nodes.
At the beginning, the tree has only one node (numbered 1 and is the root node), and every second, each node will add k child nodes. Specifically, if at the xth second this tree has p nodes, and at (x+1)th second, the number of nodes will become (k+1)×p. For the node numbered y(1≤y≤p), the generated k child nodes are numbered in [p+(y−1)×k+1,p+y×k].
Now you want to know the lowest common ancestors of two nodes x,y.
For two nodes u and v of a rooted tree T, the lowest common ancestors LCA(T,u,v) represents a node x such that x is the ancestor of u and v and the depth of x is as large as possible. Here, a node can also be its own ancestor.

输入格式

The input consists of multiple test cases.
The first line contains a single integer T(1≤T≤105 ), indicating there are T test cases.
In each test case:
The only line contains three positive integers k,x,y(2≤k,x,y≤1018), representing the parameters and query nodes of the tree.

输出格式

For each case,the output contains a single number, indicating the the lowest common ancestors of the query nodes.

输入样例

3
2 6 7
2 4 5
3 20 2

输出样例

2
1
2

代码长度限制 16 KB
时间限制 1000 ms
内存限制 128 MB

题解

思路解析

我们根据题目中的由父亲推出儿子的式子可以得到逆变换的由儿子推出父亲的式子
F a t h e r = ⌊ S o n − P − 1 K ⌋ + 1 Father=\lfloor \frac{Son-P-1}{K}\rfloor+1 Father=KSonP1+1
现在问题是这个P怎么求呢。
我们可以发现每次都增长为(k+1)^n
P n = P n − 1 × k + P n − 1 = F n − 1 × ( k + 1 )   P n = { 1 , t = 0 P t − 1 × ( k + 1 ) , O t h e r s   P n = ( k + 1 ) t P_{n}=P_{n-1}\times k+P_{n-1}=F_{n-1}\times (k+1)\\ \\ \space\\P_{n}=\begin{cases} 1&,t= 0\\ P_{t-1}\times (k+1)& ,Others \end{cases}\\ \\ \space\\ P_{n}=(k+1)^t Pn=Pn1×k+Pn1=Fn1×(k+1) Pn={1Pt1×(k+1),t=0,Others Pn=(k+1)t
我们知道如果用long long 和unsigned long long 的时候乘到边界容易溢出,如果溢出了那么我们就无法准确的得到这个数的结果了。
我们可以采用一个double 的预实验变量,因为double可以指数计算,而我们可以不需要将他计算的非常准确。若测试变量的数值大于1e8那么我们的long long 的真实结果就可以停止计算了。
这里值得一提的是,double 的最大值可以在iostream头文件下用
cout<<DBL_MAX<<endl;的方法实现,但是并不是所有OJ都可以使用这条语句的。
这里测得的结果为1.79769e+308
最后找父亲的关系就很简单了,只要他俩的数字不一样,那么谁大让谁变成自己的父亲,然后继续比较,直到比较出一样的结果为止,而且1的父亲是1,不用担心超范围的一些小错误。
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
#define Find(now) ((now - 1 - P[(lower_bound(P, P + cnt, now) - P - 1)]) / k + 1)
ll P[40], k, x, y;
int cnt;
void GetLastP()
{
	double mark = 1.0;
	P[0] = 1;
	cnt = 1;
	ll temp = k + 1;
	while (true)
	{
		mark *= temp;
		if (mark > 1e18)
		{
			P[cnt++] = 2e18;
			return;
		}
		else P[cnt++] = P[cnt - 1] * temp;
	}
}
int main()
{
	int T = read;
	while (T--)
	{
		k = read, x = read, y = read;
		GetLastP();
		while (x != y)
		{
			if (x < y)y = Find(y);
			else x = Find(x);
		}
		print(x);
	}
}

G-Good Permutation

题目

题目描述

For a permutation P of length n, we define m x l , r = m a x i − l r P i mx_{l,r}=max_{i-l}^{r}P_{i} mxl,r=maxilrPi, m n l , r = m i n i = l r P i mn_{l,r}=min_{i=l}^{r}P_{i} mnl,r=mini=lrPi
For a permutation, we call it the good interval if and only if m x l , r − m n l , r = r − l mx_{l,r}-mn_{l,r}=r-l mxl,rmnl,r=rl for a interval [ l , r ] ( 1 ≤ l ≤ r ≤ n ) [l,r](1\le l\le r\le n) [l,r](1lrn).
You have some requirements for permutations, you hope that the generated permutations have some good intervals, Specifically, you have m restrictions, and the i th restriction requires the interval [l,r] to be a good interval ,and you want to know the number of such permutations. The answer can be very large, you need to output the result of the answer modulo 109 + 7. The input guarantees that for any two restrictions, there are only inclusive and disjoint relations.

输入格式

The first line contains two positive integer n,m (1≤n,m≤106 ), indicating the length of the permutation and the number of restrictions.
The next m lines, each line contains two positive integers l i , r i ( 1 ≤ l i ≤ r i ≤ n ) l_{i},r_{i}(1\le l_{i}\le r_{i}\le n) li,ri(1lirin), indicating the ith restriction.
For any two restrictions 1 ≤ i , j ≤ m 1\le i,j \le m 1i,jm, if l i > l i l_{i} > l_{i} li>li, then r i ≤ r j r_{i}\le r_{j} rirj or r j < l i r_{j} < l_{i} rj<li.

输出格式

Output a line with a positive integer indicating the number of permutations that meet the requirements.

输入样例

5 3
1 5
1 4
1 3

输出样例

24

代码长度限制 16 KB
时间限制 1000 ms
内存限制 256 MB

题解

思路解析

题目要求所选的区间内的最大值和最小值的差和我的范围的差值是一致的,这说明了一个问题。这里面的数必须是连续的几个任意序数字。
我们直到这里的区间是有可能重复,但是不会重叠的一个区间,也就是说子区间和兄弟区间这种是很容易区分出来的。
那么我们接下来我们可以去思考,这些区间有什么关系。
我们以
10
1 10
1 7
8 10
1 2
3 4
5 7
4 4
举例子
请添加图片描述我们可以发现每一层下面的我们是可以先不用处理的,这里子区间的作用无非就是将我们所有的选数方式乘上我们每一个子序列里的一些限制条件后的结果。所以我们限制看看在长度为101-3区间和5-8区间的情况。这里有两个区间,我们怎么去统计这个区间内的所有选数方法呢?我们刚才已经知道了,我们选择的区间里的数字一定是一组连续的可以混乱的数字。那么我们怎么截取区间呢?,我们可以把每个位置都看作一个选择器,只不过没有区间长度的长度定为1,那么我们就可以按照全排列的方法去选择数了。
一共有个选择器,他们的长度分别为3 4 1 1 1,3 和4的来自所选区间,而剩下的1则是每一个位单独的选择区间,其区间范围为1
在这里插入图片描述
这样我们只需要全排列选择器的范围,我们就可以,列出来所有选数的组合情况,那么接下来对于每一种情况的结果是一样的,都是每一组里的处理的结果连乘就可以了。
所以我们对于每一组我们都可以看作一个选择器,单独的看作一个选择器,那么我们一共可以得到选择器的个数为 n + k − ∑ i = 1 k l e n i n+k-\sum_{i=1}^{k}len_{i} n+ki=1kleni,对其全排列我们就可以知道所有的选择情况了。
对于每个子区间都是执行的同样的操作,如果都是一个的话那是最好的情况,就是全排列了。最终我们需要把算出来的结果返回给其父亲,作为他的这一组的价值。
所以最终我们是求出来所有组的价值乘在一起后,做一次选择器全排列即可。

下面讨论如何找到一个区间的子区间呢?
我们知道这个区间是有严格关系的,因为他说了guarantee(这个词,博主学了好几天终于记住了QAQ)
那么我们先做一下排序。L升序,R降序排序。在这里插入图片描述
我们从上往下走,如果发现我自己比所谓的可能的父亲的区间R小于FR,那么我一定就是他的儿子,然后我接下来就不能继续在这一层继续看了,因为接下来极有可能是我的儿子,所以这时候需要dfs进入下一层,如果发现区间不匹配,那么就说明了,我们一定不会是父子关系,那么我们就返回。如果兄弟也不是,再返回,直到返回可为止。
当意识到我是其儿子的时候就要将自己的pos列入其数组中。
最后我们分治计算就可以了。
题目中还说了,输入有可能重复,手写一个filter就行。
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
ll n, m;
const ll mod = 1e9 + 7;
struct node
{
	ll L, R;
}section[1000005];
bool cmp(node a, node b)
{
	if (a.L == b.L)return a.R > b.R;
	return a.L < b.L;
}
ll FAC[1000005];
ll pos = 1;
vector<ll>son[1000005];
void dfs(ll fa, ll FL, ll FR)
{
	while (pos <= m)
	{
		if (section[pos].R <= FR)
		{
			son[fa].push_back(pos++);
			dfs(pos - 1, section[pos - 1].L, section[pos - 1].R);
		}
		else return;
	}
}
ll fac(node temp)
{
	return FAC[temp.R - temp.L + 1];
}
void filter()
{
	int ip = 1;
	for (int i = 2; i <= m; i++)
		if (section[i].L != section[ip].L || section[i].R != section[ip].R)
			section[++ip] = section[i];
	m = ip;
}
ll find(ll now)
{
	ll len = section[now].R - section[now].L + 1;
	if (now == 0)len = n;
	ll res = 1;
	ll totlen = 0;
	for (int i = 0; i < son[now].size(); i++)
	{
		node temp = section[son[now][i]];
		totlen += temp.R - temp.L + 1;
		if (son[son[now][i]].empty())
			res *= fac(section[son[now][i]]);
		else
		{
			res *= find(son[now][i]);
		}
		res %= mod;
	}
	return res * FAC[len - totlen + son[now].size()] % mod;
}
int main()
{
	FAC[0] = 1;
	for (ll i = 1; i < 1000005; i++)
		FAC[i] = (FAC[i - 1] * i) % mod;
	n = read, m = read;
	for (int i = 1; i <= m; i++)
	{
		section[i].L = read;
		section[i].R = read;
	}
	sort(section + 1, section + m + 1, cmp);
	filter();
	dfs(0, 0, n + 1);
	print(find(0));
}

J-A Game about Increasing Sequences

题目

题目描述

Alice and Bob like playing games.
The game is played on a sequence of length n. Alice and Bob take turns performing the operation, with Alice going first.
In each operation, the player can remove an element from the beginning or the end of the sequence.
If this operation is not the first operation of the game, the removed element must be strictly greater than all the previously removed elements.
The player who cannot perform the operation loses.
Please determine who will win the game if both Alice and Bob play the game optimally.

输入格式

The first line contains a single integers n(1≤n≤105),representing the length of the sequence.
The second line contains n integers a 1 , a 2 , . . . , a n ( 1 ≤ a i ≤ 1 0 5 ) a_{1},a_{2},...,a_{n}(1\le a_{i}\le10^5) a1,a2,...,an(1ai105), representing the sequence.

输出格式

For each test case, print “Alice” if Alice will win the game, otherwise print “Bob”.

输入样例

3
1 3 2

输出样例

Bob

代码长度限制 16 KB
时间限制 1000 ms
内存限制 128 MB

题解

思路解析

这题经典博弈,稍微思考我们能得到以下几个关键信息,这两端,我们可以做到拿了一端立刻堵死另一端。所以我们很容易想到统计两端严格递增的数量。
而且如果只有一端可走,那么偶数时候先手必输。
于是我们可以枚举以下几种情况
在这里插入图片描述
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
ll save[100005];
int main()
{
	int n = read;
	for (int i = 0; i < n; i++)save[i] = read;
	ll L = 0, R = n - 1;
	ll cnt[2] = {1,1};
	while (save[L + 1] > save[L])L++,cnt[0]++;
	while (save[R - 1] > save[R])R--,cnt[1]++;
	if ((cnt[0] & 1) || (cnt[1] & 1))puts("Alice");
	else puts("Bob");
}

L-Quadruple

题目

题目描述

You have a string s of length n, the index starts from 0, and the string contains only ‘I’, ‘C’, ‘P’ three types of characters.
You want to do some practice with this string.
There are Q queries in total.
In each query, two integers u i u_{i} ui, v i v_{i} vi are given.Let string t i t_{i} ti be the substring of string s starting at index min( u i u_{i} ui, v i v_{i} vi) and ending at index max( u i u_{i} ui, v i v_{i} vi).
Then ask how many different kinds of array a are good.
An array a is good if and only if the following conditions are met:

  • The length of the array is 4.
  • t a 1 t_{a_{1}} ta1=‘I’, t a 2 t_{a_{2}} ta2=‘C’, t a 3 t_{a_{3}} ta3=‘P’, t a 4 t_{a_{4}} ta4=‘C’.
  • a 1 < a 2 < a 3 < a 4 a_{1} < a_{2} < a_{3} < a_{4} a1<a2<a3<a4

Two arrays a,b are different if and only if there is at least one number k(1≤k≤4) that satisfies a k ≠ b k a_{k}\ne b_{k} ak=bk.
Since there are so many queries, you just want to know the sum of the answers to all the queries and take the modulo 998244353.

输入格式

The first line contains 2 integers n,Q(1≤n,Q≤2000000)—representing the length of the string s and the number of queries.
The second line contains a string s.
The third line contains 4 integers x,a,b,p(1≤x,a,b<p≤1000000000).
Then calculate the arrays u and v through the following steps:

  1. For each i(1≤i≤Q) in order update x to (ax+b)modp, then set u i u_{i} ui to x mod n.
  2. For each i(1≤i≤Q) in order update x to (ax+b)modp, then set v i v_{i} vi to x mod n.

Then for each i(1≤i≤Q) in order set t i t_{i} ti to s [ m i n ( u i , v i ) , m a x ( u i , v i ) ] s[min(u_{i},v_{i}),max(u_{i},v{i})] s[min(ui,vi),max(ui,vi)]

输出格式

Only one line contains an integer representing the sum of the answers to each query, modulo 998244353.

输入样例

12 6
ICPCICPCICPC
1 233 97 10007

输出样例

11

代码长度限制 16 KB
时间限制 2000 ms
内存限制 256 MB

题解

思路解析

通过前缀的方式记录所有的组成方式,这个思路就是之前做的一个统计icpc的dp题。但是现在只不过多了一步,哦不,两步。多了一个种子解码,上一次碰见种子解码出测试数据还是在upc里,距今已经3年之久……
种子解码就没什么好说的了。我们就当正常的题做。
输入一个数据然后查询区间。
我们用前前缀思想的dp可以快速的求出来icpc的个数。
怎么求出来呢?
当前位置的icpc只有可能有前面的icp和c组成以及ic+pc和i+cpc
然后我们稍微思考一下就能知道,cpc是由前面的c+pc和cp+c,而cp又是由c+p得来的。
我们已经分析了组成的成分,那么问题来了,我们用前缀和做差的形式得到的icpc即icpc[R]-icpc[L-1]包含什么成分呢?
在这里插入图片描述
我们可以看到,左侧的ICPC的成分均在左边,而右边的ICPC是有在左边的成分组成的,所以我们要去掉。那么这个成分组成情况如下。
在这里插入图片描述
只分析I+CPC,是这个样子那么同理分析CPC
在这里插入图片描述
所以总结起来
ICPC[L,R]=ICPC[R]-ICPC[L-1]-I[L-1]*CPC[L,R]-IC[L-1]*PC[L,R]-ICP*C[L,R]
CPC[L,R]=CPC[R]-CPC[L-1]-C[L-1]*PC[L,R]-CP[L-1]*C[L,R]
PC[L,R]=PC[R]-PC[L-1]-P[L-1]*C[L,R]
C[L,R]=C[R]-C[L-1]
最后就是一堆取模运算了。
Ac Code

//#include<unordered_map>
#include<functional>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const ll less_inf = 0x3f3f3f3f;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define outl(info) out(info);puts("") 
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
inline void print(ll a, char end = '\n') { out(a); putchar(end); }
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
const int mod = 998244353;
#define add(key,val)(info[i].key=(info[i].key+val)%mod)
#define CLR(L,R) (((info[R].C-info[L-1].C)%mod+mod)%mod)
queue<int>ASKL, ASKR;
char save[2000005];
struct node
{
	ll I, C, P, IC, CP, PC, ICP, CPC, ICPC;
}info[2000005];
void Init()
{
	for (int i = 1; save[i]; i++)
	{
		info[i] = info[i - 1];
		switch (save[i])
		{
		case 'I':add(I, 1); break;
		case 'C':add(C, 1); add(IC, info[i - 1].I); add(PC, info[i - 1].P); add(CPC, info[i - 1].CP); add(ICPC, info[i - 1].ICP); break;
		case 'P':add(P, 1); add(CP, info[i - 1].C); add(ICP, info[i - 1].IC); break;
		}
	}
}
int PCLR(int L, int R)
{
	return ((info[R].PC - info[L - 1].PC - info[L - 1].P * CLR(L, R) % mod) % mod + mod) % mod;
}
int CPCLR(int L, int R)
{
	return ((info[R].CPC - info[L - 1].CPC - info[L - 1].C * PCLR(L, R) % mod - info[L - 1].CP * CLR(L, R) % mod) % mod + mod) % mod;
}
int ICPCLR(int L, int R)
{
	return ((info[R].ICPC - info[L - 1].ICPC - info[L - 1].I * CPCLR(L, R) % mod - info[L - 1].IC * PCLR(L, R) % mod - info[L - 1].ICP * CLR(L, R) % mod) % mod + mod) % mod;
}
int main()
{
	int n = read, Q = read;
	scanf("%s", save + 1);
	Init();
	ll x = read, a = read, b = read, p = read;
	for (int i = 1; i <= Q; i++)
	{
		x = (a * x + b) % p;
		ASKL.push(x % n + 1);
	}
	for (int i = 1; i <= Q; i++)
	{
		x = (a * x + b) % p;
		ASKR.push(x % n + 1);
	}
	ll ans = 0;
	while (!ASKL.empty())
	{
		int L = ASKL.front();
		int R = ASKR.front();
		ASKL.pop();
		ASKR.pop();
		if (L > R)swap(L, R);
		ans = (ans + ICPCLR(L, R)) % mod;
	}
	print(ans);
}

By-Round Moon

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Round moon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值