[洛谷刷题10]

P1009 [NOIP 1998 普及组] 阶乘之和

https://www.luogu.com.cn/problem/P1009

题目描述

用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!++n! n ≤ 50 n \le 50 n50)。

其中 ! 表示阶乘,定义为 n ! = n × ( n − 1 ) × ( n − 2 ) × ⋯ × 1 n!=n\times (n-1)\times (n-2)\times \cdots \times 1 n!=n×(n1)×(n2)××1。例如, 5 ! = 5 × 4 × 3 × 2 × 1 = 120 5! = 5 \times 4 \times 3 \times 2 \times 1=120 5!=5×4×3×2×1=120

输入格式

一个正整数 n n n

输出格式

一个正整数 S S S,表示计算结果。

输入输出样例 #1

输入 #1

3

输出 #1

9

说明/提示

【数据范围】

对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1n50

【其他说明】

注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n ≤ 20 n \le 20 n20,使用书中的代码无法通过本题。

如果希望通过本题,请继续学习第八章高精度的知识。

NOIP1998 普及组 第二题

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

int Add[109];
int Mul[109];

int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

    int n;
    cin >> n;
    Add[0] = 1;
    Mul[0] = 1;
    int i,j;
    for(i=2;i<=n;i++){
        for(j=0;j<100;j++){
            Mul[j]*=i;
        }
        for(j=0;j<100;j++){
            if (Mul[j]>9){
                Mul[j+1] += Mul[j]/10;
                Mul[j]%=10;
            }
        }
        for(j=0;j<100;j++){
            Add[j]+=Mul[j];
            if (Add[j]>9) {
                Add[j+1] += Add[j]/10;
                Add[j]%=10;
            }
        }
    }
    for(i=100;i>=0&&Add[i]==0;i--);
    for(j=i;j>=0;j--){
        cout << Add[j];
    }
    return 0;
}

B3977 [语言月赛 202405] 更好的交换

https://www.luogu.com.cn/problem/B3977

题目描述

小 S 有一个奇怪的机关拼图。这个拼图可以看作一个 n n n n n n 列的方阵 A A A,第 i i i 行第 j j j 列的位置上有一个正整数 A i , j A_{i, j} Ai,j

与寻常拼图不同的是,这个机关拼图上的数字不能随意移动,必须按照如下规则之一操作:

  • 选择拼图上的第 x x x 行和第 y y y 行,交换这两
  • 选择拼图上的第 x x x 列和第 y y y 列,交换这两

为了复原这个拼图,小 S 将会操作共 m m m 次,每次操作格式如下:

  • 1 x y,表示交换第 x x x 行和第 y y y 行;
  • 0 x y,表示交换第 x x x 列和第 y y y 列;

请你输出复原后的拼图。

输入格式

第一行,两个正整数 n n n m m m,分别表示拼图的行数、列数和总操作次数。
接下来 n n n 行,每行 n n n 个正整数 A i , j A_{i, j} Ai,j,表示拼图上第 i i i 行,第 j j j 列上的数字。
接下来 m m m 行,每行三个正整数 o p , x , y op, x, y op,x,y,其中 o p op op 表示操作类型, x , y x, y x,y 代表被操作的行号或列号。

输出格式

输出共 n n n 行,每行 n n n 个正整数,表示复原后的拼图。

输入输出样例 #1

输入 #1

3 2
4 5 6
3 2 1
9 8 7
0 2 3
0 2 2

输出 #1

4 6 5 
3 1 2 
9 7 8

输入输出样例 #2

输入 #2

3 2
11 12 13
21 22 23
31 32 33
1 2 3
0 2 3

输出 #2

11 13 12 
31 33 32 
21 23 22

输入输出样例 #3

输入 #3

4 4               
12 32 42 82
53 43 34 98
90 32 42 53
37 17 88 10
0 2 4
1 2 4
0 1 4
1 1 3

输出 #3

32 53 42 90 
17 10 88 37 
32 82 42 12 
43 98 34 53

说明/提示

样例 1 解释

第一次操作,交换了第 2 2 2 列和第 3 3 3 列;第二次操作,没有发生变化。

样例 2 解释

第一次操作,交换第 2 2 2 行和第 3 3 3 行,拼图变为:
11   12   13 31   32   33 21   22   23 \begin{aligned} 11 \ 12 \ 13\\ \textcolor{red}{31 \ 32 \ 33}\\ \textcolor{blue}{21 \ 22 \ 23} \end{aligned} 11 12 1331 32 3321 22 23

第二次操作,交换第 2 2 2 列和第 3 3 3 列,拼图变为:
11   13   12 31   33   32 21   23   22 \begin{aligned} 11 \ \textcolor{red}{13} \ \textcolor{blue}{12} \\ 31 \ \textcolor{red}{33} \ \textcolor{blue}{32} \\ 21 \ \textcolor{red}{23} \ \textcolor{blue}{22} \end{aligned} 11 13 1231 33 3221 23 22

数据范围

对于前 30 % 30 \% 30% 的数据,保证每一行数字相同;
对于前 60 % 60 \% 60% 的数据,保证 1 ≤ m ≤ 3 × 1 0 3 1 \leq m \leq 3 \times 10^3 1m3×103
对于 100 % 100 \% 100% 的数据,保证 1 ≤ m ≤ 1 0 6 , 1 ≤ n , A i , j ≤ 1 0 3 , 1 ≤ x , y ≤ n 1 \leq m \leq 10^6, 1 \leq n, A_{i, j} \leq 10^3, 1 \leq x, y \leq n 1m106,1n,Ai,j103,1x,yn 0 ≤ o p ≤ 1 0 \leq op \leq 1 0op1

解题思路

不难发现,行和列之间的修改是无关的。我们可以将行和列的操作分开处理。

现在我们假设只有行操作,没有列操作该如何处理。

实际上,我们可以不用真的去交换每一行。考虑用一个数组 row[i] 来表示当前第 i 行里所存储的是初始的哪一行。那么,对于一次交换 x行和 y行的操作,我们只需要交换 row[x]row[y] 即可。

同理,如果只有列操作,没有行操作,该如何处理呢?可以开一个 col[i] 数组,表示当前第 i 列里存储的是初始的哪一列,然后也只需要交换 col[x]col[y] 即可。

由于行和列的操作互不相干,所以以上两个方法可以同时进行。也就是说,我们只要用数组 rowcol 来代替每次的修改就可以了:

接下来考虑如何输出答案。在用二重循环枚举行和列时,直接输出 a[row[i]][col[j]] 即可:

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

const int N = 1e3+9;
int a[N][N];
int row[N],col[N];

int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    
    int n,m;
    cin >> n >> m;
    for(int i=1;i<=n;i++){
        row[i] = i;
    }
    for(int i=1;i<=n;i++){
        col[i]=i;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin >> a[i][j];
        }
    }
    while(m--){
        int op;
        cin >> op;
        int x,y;
        cin >> x >> y;
        if(op == 1){
            swap(row[x],row[y]);
        }
        else{
            swap(col[x],col[y]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout << a[row[i]][col[j]] << ' ';
        }
        cout << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Almond_s

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

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

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

打赏作者

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

抵扣说明:

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

余额充值