2.20.....

P1601 A+B Problem(高精)

题目描述

高精度加法,相当于 a+b problem,不用考虑负数

输入格式

分两行输入。a,b≤10500。

输出格式

输出只有一行,代表 a+b 的值。

输入输出样例

输入 #1复制

1
1

输出 #1复制

2

输入 #2复制

1001
9099

输出 #2复制

10100

说明/提示

20% 的测试数据,0≤a,b≤109;

40% 的测试数据,0≤a,b≤1018。

import java.math.BigInteger;
import java.util.*;

public class Main {
	public static void main(String args[]) {
		Scanner in=new Scanner(System.in);
		BigInteger a=new BigInteger(in.nextBigInteger()+"");
		BigInteger b=new BigInteger(in.nextBigInteger()+"");
		System.out.println(a.add(b));
		
		
		
		}
}

BigInteger 的用法

 

BigInteger 类用于处理任意大小的整数,它可以处理比 int 和 long 类型所能表示的范围大得多的整数。

1. 导入 BigInteger 类
 

收起

java

import java.math.BigInteger;
2. 创建 BigInteger 对象
 
  • 使用字符串构造:最常用的方式,通过传入一个表示整数的字符串来创建 BigInteger 对象。
 

收起

java

BigInteger num1 = new BigInteger("12345678901234567890");
 
  • 使用静态常量BigInteger 类提供了一些静态常量,如 ZEROONE 和 TEN
 

收起

java

BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger ten = BigInteger.TEN;
3. 基本运算
 
  • 加法:使用 add 方法。
 

收起

java

BigInteger resultAdd = num1.add(one);
 
  • 减法:使用 subtract 方法。
 

收起

java

BigInteger resultSubtract = num1.subtract(one);
 
  • 乘法:使用 multiply 方法。
 

收起

java

BigInteger resultMultiply = num1.multiply(ten);
 
  • 除法:使用 divide 方法。
 

收起

java

BigInteger resultDivide = num1.divide(ten);
 
  • 取模:使用 mod 方法。
 

收起

java

BigInteger resultMod = num1.mod(ten);
4. 比较大小
 

使用 compareTo 方法,返回值为 -1(小于)、0(等于)或 1(大于)。

 

收起

java

int comparison = num1.compareTo(one);

BigDecimal 的用法

 

BigDecimal 类用于处理任意精度的十进制数,常用于需要高精度计算的金融领域。

1. 导入 BigDecimal 类
 

收起

java

import java.math.BigDecimal;
2. 创建 BigDecimal 对象
 
  • 使用字符串构造:推荐使用这种方式,避免使用 double 类型构造时可能出现的精度问题。
 

收起

java

BigDecimal num2 = new BigDecimal("123.456");
 
  • 使用 double 或 int 构造:不推荐用于高精度计算,因为 double 类型存在精度问题。
 

收起

java

BigDecimal num3 = new BigDecimal(123.456);
3. 基本运算
 
  • 加法:使用 add 方法。
 

收起

java

BigDecimal resultAddDecimal = num2.add(new BigDecimal("1.23"));
 
  • 减法:使用 subtract 方法。
 

收起

java

BigDecimal resultSubtractDecimal = num2.subtract(new BigDecimal("1.23"));
 
  • 乘法:使用 multiply 方法。
 

收起

java

BigDecimal resultMultiplyDecimal = num2.multiply(new BigDecimal("2.0"));
 
  • 除法:使用 divide 方法,需要指定精度和舍入模式。
 

收起

java

BigDecimal resultDivideDecimal = num2.divide(new BigDecimal("3.0"), 2, BigDecimal.ROUND_HALF_UP);
4. 设置精度和舍入模式
 

divide 方法需要指定精度和舍入模式,常见的舍入模式有:

 
  • ROUND_HALF_UP:四舍五入。
  • ROUND_DOWN:直接舍去。
  • ROUND_UP:直接进位。

 

P1249 最大乘积 

题目描述

一个正整数一般可以分为几个互不相同的自然数的和,如 3=1+2,4=1+3,5=1+4=2+3,6=1+5=2+4。

现在你的任务是将指定的正整数 n 分解成若干个互不相同的自然数(也可以不分解,就是这个数字本身)的和,且使这些自然数的乘积最大。

输入格式

只一个正整数 n,(3≤n≤10000)。

输出格式

第一行是分解方案,相邻的数之间用一个空格分开,并且按由小到大的顺序。

第二行是最大的乘积。

输入输出样例

输入 #1复制

10

输出 #1复制

2 3 5
30
import java.util.Scanner;

public class Main {
    // 定义数组存储拆分的数和乘积结果
    static int[] a = new int[10001];
    static int[] s = new int[10001];
    // 输入的数 n 和乘积结果的长度
    static int n;
    static int len = 1;

    // 乘法函数,模拟大整数乘法
    public static void mul(int x) {
        // 每一位乘以 x
        for (int i = 1; i <= len; i++) {
            s[i] *= x;
        }
        // 处理进位
        for (int i = 1; i <= len; i++) {
            s[i + 1] += s[i] / 10;
            s[i] %= 10;
        }
        // 如果最高位还有进位,增加长度并继续处理进位
        while (s[len + 1] > 0) {
            len++;
            s[len + 1] += s[len] / 10;
            s[len] %= 10;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 读取输入的数 n
        n = scanner.nextInt();
        scanner.close();

        // 处理特殊情况 n = 3 和 n = 4
        if (n == 3) {
            System.out.println(3);
            System.out.println(3);
            return;
        }
        if (n == 4) {
            System.out.println(4);
            System.out.println(4);
            return;
        }

        // 初始化乘积结果
        s[0] = s[1] = 1;
        // 拆分和累加的和以及拆分的数的个数
        int sum = 0;
        int tot = 0;
        // 将 n 拆分为从 2 开始的连续自然数的和
        for (int i = 2; sum < n; i++) {
            a[++tot] = i;
            sum += i;
        }

        // 根据拆分结果进行调整
        if (sum > n + 1) {
            a[sum - n - 1] = 0;
        } else if (sum == n + 1) {
            a[tot]++;
            a[1] = 0;
        }

        // 输出拆分的数并计算乘积
        for (int i = 1; i <= tot; i++) {
            if (a[i] != 0) {
                System.out.print(a[i] + " ");
                mul(a[i]);
            }
        }
        System.out.println();

        // 输出乘积结果
        for (int i = len; i >= 1; i--) {
            System.out.print(s[i]);
        }
        System.out.println();
    }
}
观察性质

先举出几个简单的例子:

  • 5→2×3
  • 6→2×4
  • 9→2×3×4
  • 10→2×3×5

我们观察到,大部分分解出来的数都是较为连续的。

得出结论

考虑这样一种贪心策略:

首先构造出连续一段自然数,使得和恰好大于或等于 n ,然后找到一个合适的数并更改(如果等于 n 就不更改),使得和满足要求。

例如分解一个数 15 :

  • 首先找到连续一段自然数: 2+3+4+5+6>15 (为什么要从 2 开始而不是 3 或更大?请思考);
  • 发现 2+3+4+5+6=20 ,恰好与 15 相差 5 ;
  • 把 5 删掉,得到 2+3+4+6=15 ,计算答案。

若找到的和与 n 相差 1 ,可以直接删除 2 并将最后一个数加上 1 。

注意:当 n=3,4 时并不符合上述的贪心策略,需要特判。

lna+lnb=ln(a×b) dp的方法

P4924 [1007] 魔法少女小Scarlet 

题目描述

Scarlet 最近学会了一个数组魔法,她会在 n×n 二维数组上将一个奇数阶方阵按照顺时针或者逆时针旋转 90∘。

首先,Scarlet 会把 1 到 n2 的正整数按照从左往右,从上至下的顺序填入初始的二维数组中,然后她会施放一些简易的魔法。

Scarlet 既不会什么分块特技,也不会什么 Splay 套 Splay,她现在提供给你她的魔法执行顺序,想让你来告诉她魔法按次执行完毕后的二维数组。

输入格式

第一行两个整数 n,m,表示方阵大小和魔法施放次数。

接下来 m 行,每行 4 个整数 x,y,r,z,表示在这次魔法中,Scarlet 会把以第 x 行第 y 列为中心的 2r+1 阶矩阵按照某种时针方向旋转,其中 z=0 表示顺时针,z=1 表示逆时针。

输出格式

输出 n 行,每行 n 个用空格隔开的数,表示最终所得的矩阵

输入输出样例

输入 #1复制

5 4
2 2 1 0
3 3 1 1
4 4 1 0
3 3 2 1

输出 #1复制

5 10 3 18 15
4 19 8 17 20
1 14 23 24 25
6 9 2 7 22
11 12 13 16 21

说明/提示

对于50%的数据,满足 r=1

对于100%的数据 1≤n,m≤500,满足 1≤x−r≤x+r≤n,1≤y−r≤y+r≤n。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 定义二维数组 g 用于存储原始矩阵,f 作为临时数组
        int[][] g = new int[510][510];
        int[][] f = new int[510][510];
        int tot = 0;

        // 读取矩阵的大小 n 和操作的次数 m
        int n = scanner.nextInt();
        int m = scanner.nextInt();

        // 初始化矩阵 g,为每个元素赋值
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                g[i][j] = ++tot;
            }
        }

        // 进行 m 次操作
        for (int i = 1; i <= m; i++) {
            // 读取操作的参数:中心点坐标 (a, b)、半径 r 和操作类型 opt
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            int r = scanner.nextInt();
            int opt = scanner.nextInt();

            if (opt == 0) {
                // 顺时针旋转操作
                for (int x = a - r; x <= a + r; x++) {
                    for (int y = b - r; y <= b + r; y++) {
                        f[a - b + y][a + b - x] = g[x][y];
                    }
                }
                // 将临时数组 f 的值复制回矩阵 g
                for (int x = a - r; x <= a + r; x++) {
                    for (int y = b - r; y <= b + r; y++) {
                        g[x][y] = f[x][y];
                    }
                }
            } else {
                // 逆时针旋转操作
                for (int x = a - r; x <= a + r; x++) {
                    for (int y = b - r; y <= b + r; y++) {
                        f[a + b - y][b - a + x] = g[x][y];
                    }
                }
                // 将临时数组 f 的值复制回矩阵 g
                for (int x = a - r; x <= a + r; x++) {
                    for (int y = b - r; y <= b + r; y++) {
                        g[x][y] = f[x][y];
                    }
                }
            }
        }

        // 输出最终的矩阵 g
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                System.out.print(g[i][j] + " ");
            }
            System.out.println();
        }

        scanner.close();
    }
}

P1518 [USACO2.4] 两只塔姆沃斯牛 The Tamworth Two

题目描述

两只牛逃跑到了森林里。Farmer John 开始用他的专家技术追捕这两头牛。你的任务是模拟他们的行为(牛和 John)。

追击在 10×10 的平面网格内进行。一个格子可以是:一个障碍物,两头牛(它们总在一起),或者 Farmer John。两头牛和 Farmer John 可以在同一个格子内(当他们相遇时),但是他们都不能进入有障碍的格子。

一个格子可以是:

  • . 空地;
  • * 障碍物;
  • C 两头牛;
  • F Farmer John。

这里有一个地图的例子:

*...*.....
......*...
...*...*..
..........
...*.F....
*.....*...
...*......
..C......*
...*.*....
.*.*......

牛在地图里以固定的方式游荡。每分钟,它们可以向前移动或是转弯。如果前方无障碍(地图边沿也是障碍),它们会按照原来的方向前进一步。否则它们会用这一分钟顺时针转 90 度。 同时,它们不会离开地图。

Farmer John 深知牛的移动方法,他也这么移动。

每次(每分钟)Farmer John 和两头牛的移动是同时的。如果他们在移动的时候穿过对方,但是没有在同一格相遇,我们不认为他们相遇了。当他们在某分钟末在某格子相遇,那么追捕结束。

读入十行表示地图。每行都只包含 10 个字符,表示的含义和上面所说的相同。保证地图中只有一个 F 和一个 CF 和 C 一开始不会处于同一个格子中。

计算 Farmer John 需要多少分钟来抓住他的牛,假设牛和 Farmer John 一开始的行动方向都是正北(即上)。 如果 John 和牛永远不会相遇,输出 0。

输入格式

输入共十行,每行 10 个字符,表示如上文描述的地图。

输出格式

输出一个数字,表示 John 需要多少时间才能抓住牛们。如果 John 无法抓住牛,则输出 0。

输入输出样例

输入 #1复制

*...*.....
......*...
...*...*..
..........
...*.F....
*.....*...
...*......
..C......*
...*.*....
.*.*......

输出 #1复制

49

说明/提示

翻译来自NOCOW

USACO 2.4

import java.util.Scanner;

public class Main {
    static char[][] m = new char[12][12]; // 地图
    static int[] f = new int[3]; // 农夫
    static int[] c = new int[3]; // 奶牛
    static int ans, tdz; // 秒数,专属值
    static boolean[] zt = new boolean[200000]; // 扩大数组大小避免越界

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 初始化地图边界
        for (int i = 0; i <= 11; i++) {
            for (int j = 0; j <= 11; j++) {
                m[i][j] = '*';
            }
        }

        // 读取地图
        for (int i = 1; i <= 10; i++) {
            String line = scanner.nextLine().trim();
            for (int j = 1; j <= 10; j++) {
                m[i][j] = line.charAt(j - 1);
                if (m[i][j] == 'F') {
                    f[1] = i;
                    f[2] = j;
                }
                if (m[i][j] == 'C') {
                    c[1] = i;
                    c[2] = j;
                }
            }
        }

        // 模拟每秒
        while (pd()) {
            tdz = f[1] + f[2] * 10 + c[1] * 100 + c[2] * 1000 + f[0] * 10000 + c[0] * 40000;
            if (tdz >= zt.length || tdz < 0) { // 额外检查防止意外越界
                System.out.println(0);
                return;
            }
            if (zt[tdz]) {
                System.out.println(0);
                return;
            }
            zt[tdz] = true;
            move(f[1], f[2], f[0], 0);
            move(c[1], c[2], c[0], 1);
            ans++;
        }
        System.out.println(ans);
    }

    static void move(int x, int y, int mi, int h) {
        switch (mi) {
            case 0: // 北
                if (m[x - 1][y] == '*') {
                    if (h == 0) f[0] = 1;
                    else c[0] = 1;
                } else {
                    if (h == 0) f[1]--;
                    else c[1]--;
                }
                break;
            case 1: // 东
                if (m[x][y + 1] == '*') {
                    if (h == 0) f[0] = 2;
                    else c[0] = 2;
                } else {
                    if (h == 0) f[2]++;
                    else c[2]++;
                }
                break;
            case 2: // 南
                if (m[x + 1][y] == '*') {
                    if (h == 0) f[0] = 3;
                    else c[0] = 3;
                } else {
                    if (h == 0) f[1]++;
                    else c[1]++;
                }
                break;
            case 3: // 西
                if (m[x][y - 1] == '*') {
                    if (h == 0) f[0] = 0;
                    else c[0] = 0;
                } else {
                    if (h == 0) f[2]--;
                    else c[2]--;
                }
                break;
        }
    }

    static boolean pd() {
        return !(f[1] == c[1] && f[2] == c[2]);
    }
}

P1591 阶乘数码

题目描述

求 n! 中某个数码出现的次数。

输入格式

第一行为 t(t≤10),表示数据组数。接下来 t 行,每行一个正整数 n(n≤1000) 和数码 a。

输出格式

对于每组数据,输出一个整数,表示 n! 中 a 出现的次数。

输入输出样例

输入 #1复制

2
5 2
7 0

输出 #1复制

1
2
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[5000];
int main()
{
    int t;
    cin>>t;
    while (t--)
    {
        for (int i=1;i<=1001;i++)
        a[i]=0;//将数组清零。
        a[1]=1;//必须设为1。不能为0,不然怎么乘都是0。
        int n,i,j,k,m;
        int p=1,jw=0;//p代表位数,jw代表进位。
        scanf("%d%d",&n,&m);
        for(i=2;i<=n;i++)//从2开始,反正任何数乘1还等于它本身。
        {
            jw=0;
            for(j=1;j<=p;j++)//高精度*单精度。
            {
                a[j]=a[j]*i+jw;//高精度*单精度+进位。
                jw=a[j]/10;//设置进位。
                a[j]=a[j]%10;
            }
            while(jw>0)//如果还有进位,处理进位。
            {
                a[j]=jw%10;
                jw/=10;
                j++;
            }
            p=j-1;
        }
        long long sum=0;
        for (i=p;i>=1;i--)//搜索n!里有几个指定数字。
        {
            if (a[i]==m)
            sum++;
        }
        cout<<sum<<endl;//输出。
    }
    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        int[] a = new int[10000]; // 足够大的数组防止越界
        
        while (t-- > 0) {
            // 初始化数组
            for (int i = 1; i <= 1000; i++) a[i] = 0;
            a[1] = 1; // 初始值为1

            int p = 1; // 当前位数
            int n = scanner.nextInt();
            int m = scanner.nextInt();

            // 计算n!
            for (int i = 2; i <= n; i++) {
                int carry = 0;
                // 逐位相乘
                for (int j = 1; j <= p; j++) {
                    a[j] = a[j] * i + carry;
                    carry = a[j] / 10;
                    a[j] %= 10;
                }
                // 处理剩余进位
                while (carry > 0) {
                    a[++p] = carry % 10;
                    carry /= 10;
                }
            }

            // 统计数字出现次数
            int count = 0;
            for (int i = p; i >= 1; i--) {
                if (a[i] == m) count++;
            }
            System.out.println(count);
        }
        scanner.close();
    }
}

import java.math.BigInteger;

public class FactorialWithBigInteger {
    public static BigInteger factorial(int n) {
        // 初始化结果为 1
        BigInteger result = BigInteger.ONE;

        // 循环计算阶乘
        for (int i = 1; i <= n; i++) {
            // 将当前数转换为 BigInteger 类型
            BigInteger current = BigInteger.valueOf(i);
            // 将结果乘以当前数
            result = result.multiply(current);
        }

        return result;
    }

    public static void main(String[] args) {
        int number = 20; // 要计算阶乘的数
        BigInteger factorialResult = factorial(number);
        System.out.println(number + " 的阶乘是: " + factorialResult);
    }
}求阶乘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值