2018年江西理工大學C語言程序設計競賽高級組部分題解

B Interesting pathshtml

  考察範圍:組合數學java

  此題是機器人走方格的變種,n*m的網格,從(1,1)走到(n,m),首先能夠明確,水平要走m-1格,豎直要走n-1格,則走到目的地的任意一條路徑必須走n+m-2格,呢麼只要肯定豎直要走的,剩下的就是水平要走的,則答案爲node

 

ios

  在Interseting paths要求左下角和右上角兩個小矩陣不能走,則須要把整個網格依據兩個小矩陣的水平和豎直邊界分爲兩部分,依次運用組合數。例如c++

灰色區域以外爲可走區域,分爲兩部分棕色,和黃色,則結果爲ide

如果這種狀況,則可分爲兩個ui

 

    

則結果爲spa

因此須要兩次分割,分別處理c到a和b到d。3d

由於n,m的範圍比較大,能夠提早預處理1到2*10^5的全部組合數和逆元。rest

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <cassert>
#include <ctime>
#include <map>
#include <set>
using namespace std;
#pragma comment(linker, "/stck:1024000000,1024000000")
#pragma GCC diagnostic error "-std=c++11"
#define lowbit(x) (x&(-x))
#define max(x,y) (x>=y?x:y)
#define min(x,y) (x<=y?x:y)
#define MAX 100000000000000000
#define MOD 998244353
#define pi acos(-1.0)
#define ei exp(1)
#define PI 3.1415926535897932384626433832
#define ios() ios::sync_with_stdio(true)
#define INF 0x3f3f3f3f
#define mem(a) ((a,0,sizeof(a)))
typedef long long ll;
const ll mod=1000000007;
ll fic[200006],jie[200006];
ll t,n,m,a,b,c,d;
ll quick_pow(ll x,ll y){//求逆元
    ll ans=1;
    while(y){
        if(y&1) ans=ans*x%mod;
        y>>=1;
        x=x*x%mod;
    }
    return ans;
}
void get_fic(){
    fic[0]=1;
    jie[0]=quick_pow(fic[0],mod-2);
    for(int i=1;i<=200004;i++){
        fic[i]=fic[i-1]*i%mod;
        jie[i]=quick_pow(fic[i],mod-2);
    }
}
int main(){
    get_fic();//預處理全部值
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&a,&b,&c,&d);
        ll ans=0;
        for(int i=c+1;i<a;i++){//豎直處理
            ll l=fic[b+i-2]*jie[b-1]%mod*jie[i-1]%mod;
            ll r=fic[m-b+n-i-1]*jie[m-b-1]%mod*jie[n-i]%mod;
            ans=(ans+(l*r)%mod)%mod;
        }
        for(int i=b+1;i<d;i++){//水平處理
            ll l=fic[c+i-2]*jie[c-1]%mod*jie[i-1]%mod;
            ll r=fic[m-i+n-c-1]*jie[m-i]%mod*jie[n-c-1]%mod;
            ans=(ans+(l*r)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

 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));
    }
}
View Code

 

 

 

F Star

  考察範圍:最小生成樹

  任意兩個主星球之間均可以選擇是否進行空間奇點壓縮,選擇不壓縮就是三維排序,壓縮就分別去掉x,y,z進行二維排序,最後跑最小生成樹便可。

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <cassert>
#include <ctime>
#include <map>
#include <set>
using namespace std;
#pragma comment(linker, "/stck:1024000000,1024000000")
#pragma GCC diagnostic error "-std=c++11"
#define lowbit(x) (x&(-x))
#define max(x,y) (x>=y?x:y)
#define min(x,y) (x<=y?x:y)
#define MAX 100000000000000000
#define MOD 1000000007
#define pi acos(-1.0)
#define ei exp(1)
#define PI 3.1415926535897932384626433832
#define ios() ios::sync_with_stdio(true)
#define INF 0x3f3f3f3f
#define mem(a) (memset(a,0,sizeof(a)))
typedef long long ll;
int fa[100005];
ll n,k;
struct f{
  ll x,y,z;
  int id;
}edge[100005];
struct node{
  int u,v;
  ll dis;
  bool operator<(const node &a) const{
    return a.dis>dis;
  }
}e[400005];
int find(int x){
  return fa[x]=(fa[x]==x?x:find(fa[x]));
}
bool cmp_xyz(f a,f b){//自定義排序
  return a.x+a.y+a.z<b.x+b.y+b.z;
}
bool cmp_xy(f a,f b){
  return a.x+a.y<b.x+b.y;
}
bool cmp_xz(f a,f b){
  return a.x+a.z<b.x+b.z;
}
bool cmp_yz(f a,f b){
  return a.z+a.y<b.z+b.y;
}
int main(){
  scanf("%lld%lld",&n,&k);
  for(int i=0;i<n;i++){
    scanf("%lld%lld%lld",&edge[i].x,&edge[i].y,&edge[i].z);
    edge[i].id=i+1;
  }
  for(int i=1;i<=n;i++)
    fa[i]=i;
  int ans=0;
  sort(edge,edge+n,cmp_xyz);
  for(int i=1;i<n;i++)
    e[ans++]=(node){edge[i].id,edge[i-1].id,edge[i].x+edge[i].y+edge[i].z-edge[i-1].x-edge[i-1].y-edge[i-1].z};
  sort(edge,edge+n,cmp_xy);
  for(int i=1;i<n;i++)
    e[ans++]=(node){edge[i].id,edge[i-1].id,edge[i].x+edge[i].y-edge[i-1].x-edge[i-1].y};
  sort(edge,edge+n,cmp_xz);
  for(int i=1;i<n;i++)
    e[ans++]=(node){edge[i].id,edge[i-1].id,edge[i].x+edge[i].z-edge[i-1].x-edge[i-1].z};
  sort(edge,edge+n,cmp_yz);
  for(int i=1;i<n;i++)
    e[ans++]=(node){edge[i].id,edge[i-1].id,edge[i].z+edge[i].y-edge[i-1].z-edge[i-1].y};
  int pos=n-1;
  sort(e,e+ans);
  ll inf=0;
  for(int i=0;i<ans && pos>0;i++){//最小生成樹kruskal寫法
    int x=find(e[i].u);
    int y=find(e[i].v);
    if(x!=y){
      inf+=e[i].dis;
      fa[x]=y;
      pos--;
    }
  }
  printf("%lld\n",inf*k);
  return 0;
}
View Code
相關文章
相關標籤/搜索