Skip to content

Commit

Permalink
problem(A1063,A1064,A1067): make them public
Browse files Browse the repository at this point in the history
  • Loading branch information
StableAgOH committed Oct 15, 2023
1 parent e235319 commit 328a7c8
Show file tree
Hide file tree
Showing 12 changed files with 502 additions and 6 deletions.
2 changes: 0 additions & 2 deletions problems/A/A1063/.gitignore

This file was deleted.

138 changes: 138 additions & 0 deletions problems/A/A1063/A1063.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# 题目描述

AgOH 和 Tifa 都非常喜欢石头剪子布游戏,他们经常进行石头剪子布比拼。某天,AgOH 准备与 Tifa 比拼石头剪子布,以决定谁才是两人中比较强的那个人。不出所料,Tifa 赢了 AgOH。

然而,AgOH 非常无耻地耍起了赖,他认为自己输只是因为大意了而没有闪,于是他决定把游戏改为三局两胜,继续与 Tifa 比拼。于是 Tifa 在万般无奈之下又赢下了 AgOH。但是 AgOH 继续耍赖,又将游戏改为了五局三胜,再一次失败后,他又把游戏改为了七局四胜……

终于,在 AgOH 将游戏改为了 $2n-1$ 局 $n$ 胜时,Tifa 的耐心消耗光了。如果这样 AgOH 仍不能胜利,那么 AgOH 就彻底输掉了,因为如果他继续耍赖,就会被 Tifa 狠狠地制裁。

也就是说,如果 AgOH 在 $1$ 局游戏中赢了 $1$ 局,或在 $3$ 局游戏中赢了 $2$ 局,……,或在 $2n-1$ 局游戏中赢了 $n$ 局,那么 AgOH 将获得胜利;否则 Tifa 将获得胜利。

饶是如此,AgOH 这一次还是输掉了游戏,但他非常不服气,还想要与 Tifa 再战三百回合。在游戏再一次开始之前,AgOH 突然想知道自己的胜率有多少,但他的数学水平还不如小学生,于是只好请你帮帮他。

注意:虽然 AgOH 石头剪子布的技术很菜,但**他与 Tifa 进行一次石头剪子布的胜率仍是 $50 \%$**

# 输入格式

一行,一个整数 $n$,含义如题意。

# 输出格式

在一行内输出 **AgOH 的胜率对 $998244353$ 取余的结果(见下方提示)**

# 输入输出样例

```input1
1
```

```output1
499122177
```

```input2
233
```

```output2
907783838
```

```input3
98765
```

```output3
176890789
```

# 说明/提示

如果你不了解取模/如何计算一个分数对一个整数取模的结果,请将以下代码粘贴到你的代码中,并**仔细阅读**下文说明:

```cpp
class mint
{
const static int mod = 998244353;
long long x;
void norm() { x = (x%mod+mod)%mod; }
public:
mint() : x(0) {}
mint(long long x) : x(x) { norm(); }
friend mint operator^(mint lhs, long long rhs)
{
mint res = 1;
for(;rhs;rhs>>=1,lhs=lhs*lhs) if(rhs&1) res = res*lhs;
return res;
}
mint operator~() { return (*this)^(mod-2); }
friend mint operator+(mint lhs, mint rhs) { return lhs.x+rhs.x; }
friend mint operator-(mint lhs, mint rhs) { return lhs.x-rhs.x; }
friend mint operator*(mint lhs, mint rhs) { return lhs.x*rhs.x; }
friend mint operator/(mint lhs, mint rhs) { return lhs*(~rhs); }
friend istream& operator>>(istream& is, mint& rhs) { is>>rhs.x; rhs.norm(); return is; }
friend ostream& operator<<(ostream& os, mint rhs) { return os<<rhs.x; }
};
```

之后,你应该使用 `mint` 而不是 `int` 来定义一个**需要在计算过程中对 $998244353$ 取余的**整数。例如:

```cpp
int x = 998244300;
x = (x+100)%998244353;
cout<<x<<endl; // 结果为:47
```

直接改为:

```cpp
mint x = 5;
x = x+100;
cout<<x<<endl; // 结果为:47
```

即可。这样,`mint` 会帮你完成计算过程中的取余,你可以像使用普通的 `int` 那样去使用 `mint`,而不必考虑对 $998244353$ 取余这件事。

`mint` 支持的操作有四则运算、幂、逆元(不了解逆元可以当做没看见)以及输入输出,具体用法见如下示例代码:

```cpp
#include <iostream>
using namespace std;
class mint { /* ... */ } // 上述代码应放置的位置
mint arr[5][4]; // 定义一个 5*4 的整数数组
int main()
{
mint x = 5;
cout<<x+5<<endl; // 结果为 10
cout<<x-10<<endl; // 结果为 998244348
mint y = x;
cout<<y*(x+2)<<endl; // 结果为 35
cout<<y/2<<endl; // 结果为 499122179
mint z; // z 的值缺省为 0
cin>>z; // 假设输入的是 3
cout<<~z<<endl; // 求逆元,结果为 332748118
cout<<(z^3)<<endl; // 求 z 的 3 次方,结果为 27,注意括号不能删
cout<<x*(z^6)<<endl; // 求 x 乘 (z 的 6 次方),结果为 3645,注意括号不能删
return 0;
}
```
在使用/计算过程中不需要取余的数不需要使用 `mint`(因为提供的 `mint` 仅实现了计算功能,并没有实现普通数字具有的比较大小等功能)。例如以下代码中的 $n$ 和 $i$ 就不需要定义成 `mint`,因为它们只是作为循环次数记录,并不参与需要取模的计算:
```cpp
// 以下代码计算 100! 对 998244353 取模的结果
int n = 100;
mint x = 1;
for(int i=1;i<=n;i++) x = x*i;
cout<<x<<endl; // 结果为:35305197
```

另注意:`mint` 不支持 `+=``-=` 等运算符,请用普通四则运算符替代。例如 `x += y` 应改为 `x = x+y`

【数据规模】

对于 $10 \%$ 的数据,$1 \leq n \leq 3$;

对于 $50 \%$ 的数据,$1 \leq n \leq 1000$;

对于 $100 \%$ 的数据,$1 \leq n \leq {10}^5$。
25 changes: 25 additions & 0 deletions problems/A/A1063/gen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef uniform_int_distribution<> rnd;
typedef uniform_int_distribution<ll> rndll;
typedef uniform_real_distribution<> rndf;
mt19937 egn(time(nullptr));
const int CASES = 20;
// ==============================

// ==============================
int main(int argc, char const* argv[])
{
for(int _t=1;_t<=CASES;_t++)
{
ofstream fout(to_string(_t)+".in");
// ==============================
if(_t<=2) fout<<_t+1<<endl;
else if(_t<=10) fout<<_t+(1000-10)<<endl;
else fout<<_t+(100000-20)<<endl;
// ==============================
fout.close();
}
return 0;
}
41 changes: 41 additions & 0 deletions problems/A/A1063/std.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <iostream>
using namespace std;
class mint
{
const static int mod = 998244353;
long long x;
void norm() { x = (x%mod+mod)%mod; }
public:
mint() : x(0) {}
mint(long long x) : x(x) { norm(); }
friend mint operator^(mint lhs, long long rhs)
{
mint res = 1;
for(;rhs;rhs>>=1,lhs=lhs*lhs) if(rhs&1) res = res*lhs;
return res;
}
mint operator~() { return (*this)^(mod-2); }
friend mint operator+(mint lhs, mint rhs) { return lhs.x+rhs.x; }
friend mint operator-(mint lhs, mint rhs) { return lhs.x-rhs.x; }
friend mint operator*(mint lhs, mint rhs) { return lhs.x*rhs.x; }
friend mint operator/(mint lhs, mint rhs) { return lhs*(~rhs); }
friend istream& operator>>(istream& is, mint& rhs) { is>>rhs.x; rhs.norm(); return is; }
friend ostream& operator<<(ostream& os, mint rhs) { return os<<rhs.x; }
};
const int maxn = 2e5+5;
mint h[maxn];
int main()
{
int n;
cin>>n;
h[0] = 1;
for(int i=1;i<=2*n-1;i++) h[i] = h[i-1]*(4*i-2)/(i+1);
mint sum=0, mul=2;
for(int i=0;i<n;i++)
{
sum = sum+h[i]/mul;
mul = mul*4;
}
cout<<sum<<endl;
return 0;
}
2 changes: 0 additions & 2 deletions problems/A/A1064/.gitignore

This file was deleted.

64 changes: 64 additions & 0 deletions problems/A/A1064/A1064.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# 题目描述

给定两个长度为 $n$ 的数列 $\{a_n \}$ 以及 $\{b_n \}$,你需要在 $a$ 中选择 $k$ 个数,然后在 $b$ 中选择所有与这 $k$ 个数的位置不同的数,并计算这 $n$ 个数的和。你需要找到一种方法使得这个和最小,并输出这个最小的和。

形式化的说,给定两个数列 $\{a_n \}$ 以及 $\{b_n \}$,你需要在集合 $R=\{1,2,\cdots,n \}$ 中选择 $k$ 个数记为集合 $S$,使得 $\sum \limits_{i \in S} a_i + \sum \limits_{i \in R-S} b_i$ 的值最小。

注意:本题有多组数据。

# 输入格式

第一行,一个整数 $t$,代表数据组数。

对于每组数据:

第一行,两个整数 $n,k$,代表数列长度和需要在数列 $a$ 中选择的数字个数。

第二行,$n$ 个整数 $a_i$,代表数列 $a$。

第三行,$n$ 个整数 $b_i$,代表数列 $b$。

# 输出格式

一行,一个整数,代表你能选择出的最小的和。

# 输入输出样例

```input1
5
6 3
1 2 3 4 5 6
1 1 4 5 1 4
5 0
1 2 3 4 5
5 4 3 2 1
5 5
1 0 1 0 1
0 1 0 1 0
2 1
8 1
1 7
5 5
1 2 3 4 5
5 4 3 2 1
```

```output1
14
15
3
2
15
```

# 说明/提示

【样例解释】

你需要在数列 $a$ 中选择 $1,3,4$,在数列 $b$ 中选择第二个以及第三个 $1$ 以及第二个 $4$,可以证明这样选择可以获得最小的和。

【数据规模】

对于 $50 \%$ 的数据,$1 \leq a_i \leq 100$;

对于 $100 \%$ 的数据,$1 \leq t \leq {10}^5,~1 \leq n \leq {10}^5,~0 \leq k \leq n,~1 \leq a_i \leq {10}^9$,并保证 $\sum n \leq 2 \times {10}^5$。
70 changes: 70 additions & 0 deletions problems/A/A1064/gen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef uniform_int_distribution<> rnd;
typedef uniform_int_distribution<ll> rndll;
typedef uniform_real_distribution<> rndf;
mt19937 egn(time(nullptr));
const int CASES = 4;
// ==============================

// ==============================
int main(int argc, char const* argv[])
{
for(int _t=1;_t<=CASES;_t++)
{
ofstream fout(to_string(_t)+".in");
// ==============================
if(_t==1)
{
int t = 2e4;
fout<<t<<endl;
for(int s=0;s<t;s++)
{
int n = 10;
fout<<n<<' '<<rnd(0,n)(egn)<<endl;
for(int i=0;i<n;i++) fout<<rnd(1,100)(egn)<<" \n"[i==n-1];
for(int i=0;i<n;i++) fout<<rnd(1,100)(egn)<<" \n"[i==n-1];
}
}
else if(_t==2)
{
int t = 10;
fout<<t<<endl;
for(int s=0;s<t;s++)
{
int n = 2e4;
fout<<n<<' '<<rnd(0,n)(egn)<<endl;
for(int i=0;i<n;i++) fout<<rnd(1,100)(egn)<<" \n"[i==n-1];
for(int i=0;i<n;i++) fout<<rnd(1,100)(egn)<<" \n"[i==n-1];
}
}
else if(_t==3)
{
int t = 2e4;
fout<<t<<endl;
for(int s=0;s<t;s++)
{
int n = 10;
fout<<n<<' '<<rnd(0,n)(egn)<<endl;
for(int i=0;i<n;i++) fout<<rnd(1,1e9)(egn)<<" \n"[i==n-1];
for(int i=0;i<n;i++) fout<<rnd(1,1e9)(egn)<<" \n"[i==n-1];
}
}
else
{
int t = 10;
fout<<t<<endl;
for(int s=0;s<t;s++)
{
int n = 2e4;
fout<<n<<' '<<rnd(0,n)(egn)<<endl;
for(int i=0;i<n;i++) fout<<rnd(1,1e9)(egn)<<" \n"[i==n-1];
for(int i=0;i<n;i++) fout<<rnd(1,1e9)(egn)<<" \n"[i==n-1];
}
}
// ==============================
fout.close();
}
return 0;
}
24 changes: 24 additions & 0 deletions problems/A/A1064/std.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+5;
int a[maxn], b[maxn], c[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++) c[i] = a[i]-b[i];
sort(c, c+n);
long long ans = 0;
for(int i=0;i<n;i++) ans += b[i];
for(int i=0;i<k;i++) ans += c[i];
cout<<ans<<'\n';
}
return 0;
}
2 changes: 0 additions & 2 deletions problems/A/A1067/.gitignore

This file was deleted.

Loading

0 comments on commit 328a7c8

Please sign in to comment.