第十三届蓝桥杯大赛软件赛省赛(Java 大学A组)


  小做一会 J A \mathrm{JA} JA 打发时间。


试题 A: 裁纸刀

本题总分: 5 5 5


【问题描述】

  小蓝有一个裁纸刀,每次可以将一张纸沿一条直线裁成两半。

  小蓝用一张纸打印出两行三列共 6 6 6 个二维码,至少使用九次裁出来,下图给出了一种裁法。

在这里插入图片描述
  在上面的例子中,小蓝的打印机没办法打印到边缘,所以边缘至少要裁 4 4 4 次。另外,小蓝每次只能裁一张纸,不能重叠或者拼起来裁。

  如果小蓝要用一张纸打印出 20 20 20 22 22 22 列共 440 440 440 个二维码,他至少需要裁多少次?

【答案提交】

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


443


  我们可以仿照两行三列时,题目给出的切分法,写出一个递归程序去计算它的切割次数,

  题目给出的方法可以抽象为两部分,

   1 、 1、 1边缘裁剪 4 4 4 次。
   2 、 2、 2选择当前纸片中连接二维码数量最多的一条线,沿其切割,分割成两个小纸片,重复此步直至纸片的某行或某列为 1 1 1

public class Test {
   

    public static void main(String[] args) {
    System.out.println(calc(20, 22) + 4); }

    static int calc(int row, int col) {
   
        if (row > col) return calc(col, row);
        if (col == 1) return row - 1;
        if (row == 1) return col - 1;
        if (row % 2 == 0) return 2 * calc(row / 2, col) + 1;
        return calc(1, col) + 2 * calc(row / 2, col) + 2;
    }
}

  当然这种方式并非绝对最优,一种较为稳妥的方式是在记忆化处理下暴搜,不过总所周知,记忆化搜索是状压 d p \mathrm{dp} dp 的递归实现,由此,我们可以在状态转移方程上研究出最优方案之间的共性,

  设状态 f i , j f_{i,j} fi,j i i i j j j 列的纸片在最优裁剪方案下的步骤数,显然有 f i , j = f j , i f_{i,j} = f_{j,i} fi,j=fj,i f i , 1 = i − 1 f_{i,1} = i-1 fi,1=i1 f i , j = min ⁡ { f i ′ , j + f i − i ′ , j , f i , j ′ + f i , j − j ′ } + 1 ∣ 1 ≤ i ′ < i , 1 ≤ j ′ < j f_{i,j}=\min\{f_{i',j}+f_{i-i',j},f_{i,j'} +f_{i,j-j'}\}+1|1\leq i' < i,1\leq j' < j fi,j=min{ fi,j+fii,j,fi,j+fi,jj}+11i<i,1j<j

  当我们知道 f i ′ , j + f i − i ′ , j f_{i',j}+f_{i-i',j} fi,j+fii,j f i , j ′ + f i , j − j ′ f_{i,j'} +f_{i,j-j'} fi,j+fi,jj 中谁更优时,不妨假设当 i + j = k + g i+j=k+g i+j=k+g f i , j = f k , g f_{i,j} = f_{k,g} fi,j=fk,g

  我们将 f i , j f_{i,j} fi,j 的表达式变形为 f i , j = min ⁡ { f i ′ , j + f i − i ′ , j + 1 , f i , j ′ + f i , j − j ′ + 1 } − 1 f_{i,j}=\min\{f_{i',j}+f_{i-i',j}+1,f_{i,j'} +f_{i,j-j'}+1\}-1 fi,j=min{ fi,j+fii,j+1,fi,j+fi,jj+1}1,将 f i , 1 = i − 1 f_{i,1} = i-1 fi,1=i1 代入式中会发现,无论怎么拆分,最后表达式一定是若干 f 1 , x + 1 f_{1,x}+1 f1,x+1 f y , 1 + 1 f_{y,1}+1 fy,1+1 − 1 -1 1 的累加,其和一定是 i × j − 1 i×j-1 i×j1

  耶,我们证明切分次数与切分方案无关,

  太棒了,草


试题 B: 寻找整数

本题总分: 5 5 5


【问题描述】

  有一个不超过 1 0 17 10^{17} 1017 的正整数 n n n,知道这个数除以 2 2 2 49 49 49 后的余数如下表所示,求这个正整数最小是多少。

在这里插入图片描述

【答案提交】

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


2022040920220409


扩展中国剩余定理


  对于一元线性同余方程组 : : { x ≡ r 1 ( m o d n 1 ) x ≡ r 2 ( m o d n 2 )   ⋮ x ≡ r k ( m o d n k ) \begin{cases} x &\equiv r_1 \pmod {n_1} \\ x &\equiv r_2 \pmod {n_2} \\ &\ \vdots \\ x &\equiv r_k \pmod {n_k} \\ \end{cases} xxxr1(modn1)r2(modn2) rk(modnk)  方程组的唯一是 x = ∑ i = 1 k r i m i i n v ( m i , n i ) ( m o d M ) x = \sum_{i=1}^kr_im_i\mathrm{inv}(m_i,n_i)\pmod M x=i=1krimiinv(mi,ni)(modM),其中 M = ∏ i = 1 k n 1 M = \prod_{i=1}^kn_1 M=i=1kn1 m i = M n i m_i = \frac{M}{n_i} mi=niM i n v ( a , b ) \mathrm{inv}(a,b) inv(a,b) a − 1 ( m o d b ) a^{-1}\pmod b a1(modb)

  可是对于 gcd ⁡ ( m i , n i ) ≠ 1 \gcd(m_i,n_i)\neq1 gcd(mi,ni)=1 的情况, i n v ( m i , n i ) \mathrm{inv}(m_i,n_i) inv(mi,ni) 不存在,此时无法使用 C R T \mathrm{CRT} CRT 求解。

  于是引入扩展中国剩余定理 ( E X C R T ) : \mathrm{(EXCRT)}: (EXCRT)

  对于 k = 2 k=2 k=2,即方程组为 : : { x ≡ r 1 ( m o d n 1 ) x ≡ r 2 ( m o d n 2 ) \begin{cases}x&\equiv r_1 \pmod {n_1} \\ x &\equiv r_2 \pmod {n_2} \\ \end{cases} { xxr1(modn1)r2(modn2)  我们将 x x x 化为不定方程 x = n 1 p + r 1 = n 2 q + r 2 x=n_1p+r_1=n_2q+r_2 x=n1p+r1=n2q+r2,移项后有 n 1 p − n 2 q = r 2 − r 1 n_1p-n_2q=r_2-r_1 n1pn2q=r2r1,若 gcd ⁡ ( n 1 , n 2 ) ∣ ( r 2 − r 1 ) \gcd(n_1,n_2)|(r_2-r_1) gcd(n1,n2)(r2r1),另 k = n 1 gcd ⁡ ( n 1 , n 2 ) k =\frac{n_1}{\gcd(n_1,n_2)} k=gcd(n1,n2)n1 g = n 2 gcd ⁡ ( n 1 , n 2 ) g =\frac{n_2}{\gcd(n_1,n_2)} g=gcd(n1,n2)n2,容易使用 E X G C D \mathrm{EXGCD} EXGCD 找到一组 p , q p,q p,q 使得 k p + q g = 1 kp+qg=1 kp+qg=1,此时 x ∗ = n 1 p + r 1 = r 2 − r 1 gcd ⁡ ( n 1 , n 2 ) p + r 1 x^*=n_1p+r_1=\frac{r_2-r_1}{\gcd(n_1,n_2)}p+r_1 x=n1p+r1=gcd(n1,n2)r2r1p+r1 同时满足两式。

  当然题目中的方程数列为 48 48 48,我们需要将 x x x 推广到更一般的形式来计算出满足全部方程的 x x x,若 x x x 存在,容易对满足 x ≡ r 1 ( m o d n 1 ) x\equiv r_1 \pmod{n_1} xr1(modn1) x ≡ r 2 ( m o d n 2 ) x\equiv r_2 \pmod{n_2} xr2(modn2) 的特解 x ∗ = n 1 p + r 1 x^* = n_1p+r_1 x=n1p+r1 构造出平凡解系 x ∗ + k l c m ( n 1 , n 2 ) x^* + k\mathrm{lcm}(n_1,n_2) x+klcm(n1,n2),将两式化为一元线性同余方程 x ≡ x ∗ ( m o d l c m ( n 1 , n 2 ) ) x \equiv x^* \pmod{\mathrm{lcm}(n_1,n_2)} xx(modlcm(n1,n2))

  这个结论是显然的,但在此之上还有个推论就是一个完全剩余系中有且仅有一个解,

  不想证,摆了。

  不过这题用 J a v a \mathrm{Java} Java 实现起来较为恶心,因为 ( 1 , 49 ] (1,49] (1,49] 中的质数有 15 15 15 个,粗劣估计它们的乘积一定是会爆 long

  叹息。

import java.math.BigInteger;

public class Test {
   

    public static void main(String[] args) {
    new Test().run(); }

    int[] R = {
    0, 0, 1, 2, 1, 4, 5, 4, 1, 2, 9, 0, 5, 10, 11, 14, 9, 0, 11, 18, 9, 11, 11, 15, 17, 9, 23, 20, 25, 16, 29, 27, 25, 11, 17, 4, 29, 22, 37, 23, 9, 1, 11, 11, 33, 29, 15, 5, 41, 46 };

    void run() {
   
        BigInteger M = BigInteger.valueOf(2), r = BigInteger.ONE;
        for (int i = 3; i <= 49; ++i) {
   
            BigInteger d = exgcd(M, BigInteger.valueOf(i));
            exgcd(M.divide(d), BigInteger.valueOf(i).divide(d));
            r = r.add(BigInteger.valueOf(R[i]).subtract(r).divide(d).multiply(p).multiply(M));
            M = lcm(M, BigInteger.valueOf(i));
            r = r.mod(M);
        }
        System.out.println(r);
    }

    BigInteger p, q;

    BigInteger exgcd(BigInteger a, BigInteger b) {
   
        if (b.equals(BigInteger.ZERO)) {
   
            q = BigInteger.ZERO;
            p = BigInteger.ONE;
            return a;
        }
        
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值