B Interesting paths
考察范围:组合数学
此题是机器人走方格的变种,n*m的网格,从(1,1)走到(n,m),首先可以明确,水平要走m-1格,竖直要走n-1格,则走到目的地的任意一条路径必须走n+m-2格,呢么只要确定竖直要走的,剩下的就是水平要走的,则答案为
。
在Interseting paths要求左下角和右上角两个小矩阵不能走,则需要把整个网格依据两个小矩阵的水平和竖直边界分为两部分,依次运用组合数。例如
灰色区域之外为可走区域,分为两部分棕色,和黄色,则结果为
若是这种情况,则可分为两个
则结果为
所以需要两次分割,分别处理c到a和b到d。
因为n,m的范围比较大,可以提前预处理1到2*10^5的所有组合数和逆元。
#include#include #include #include #include #include #include #include #include #include #include #include #include
C 三角平方数
设三角数为m,平方数为n则根据题意有n^2=(1/2)(m+1)m,化简可得 8n^2=4m^2+4m+1-1==>
(2m+1)^2-2(2n)^2=1
令x=2m+1,y=2n则有 x^2-2y^2=1可知为佩尔方程标准形式,特解为x=3,y=2,所以可以转化为矩阵乘法求任意一个解(佩尔方程)。
import java.util.*; import java.io.*; import java.math.*; public class Main{ static Scanner cin=new Scanner(System.in); static PrintWriter cout=new PrintWriter(System.out,true); public static BigInteger[][] multiply_matrix(BigInteger[][] a,BigInteger[][] b){ BigInteger[][] c=new BigInteger[2][2]; c[0][0]=BigInteger.valueOf(0); c[0][1]=BigInteger.valueOf(0); c[1][0]=BigInteger.valueOf(0); c[1][1]=BigInteger.valueOf(0); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) c[i][j]=c[i][j].add(a[i][k].multiply(b[k][j])); return c; } public static BigInteger quick_pow(int y){ BigInteger[][] ans=new BigInteger[2][2]; BigInteger[][] pos=new BigInteger[2][2]; ans[0][0]=BigInteger.valueOf(1); ans[0][1]=BigInteger.valueOf(0); ans[1][0]=BigInteger.valueOf(0); ans[1][1]=BigInteger.valueOf(1); pos[0][0]=BigInteger.valueOf(3); pos[0][1]=BigInteger.valueOf(4); pos[1][0]=BigInteger.valueOf(2); pos[1][1]=BigInteger.valueOf(3); while(y!=0){ if(y%2==1) ans=multiply_matrix(ans,pos); y=y/2; pos=multiply_matrix(pos,pos); } return ans[1][0]; } public static void main(String[] args){ int n=cin.nextInt(); BigInteger result=quick_pow(n); result=result.divide(BigInteger.valueOf(2)); cout.println(result.multiply(result)); } }
F Star
考察范围:最小生成树
任意两个主星球之间都可以选择是否进行空间奇点压缩,选择不压缩就是三维排序,压缩就分别去掉x,y,z进行二维排序,最后跑最小生成树即可。
#include#include #include #include #include #include #include #include #include #include #include #include #include