ACdream Online Judge 1093

女神的正多面体

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 128000/64000 KB (Java/Others)
Problem Description

      EOF女神灰常喜欢整齐的东西,例如多面体中最喜欢的就是正多面体。正多面体的定义为:指每个面都是全等的正多边形的多面体。欧拉大人告诉我们,正多面体只有正四面体(正三棱锥),正六面体(立方体),正八面体(钻石?),正十二面体,还有正二十面体。后面两种太复杂了,EOF女神不喜欢。下面是前三种多面体的图片,EOF女神给每个多面体的每个顶点都编号了。

    EOF女神想知道,如果从其中一个点出发,每一步可以沿着棱走到另一个顶点,k步之内从到达指定的顶点有多少种走法?(P.S.路径中只要有一个顶点不一样即视为不同的走法)。EOF女神知道结果会很庞大,因此只要知道除以1000000007的余数就可以了。

Input

    先输入一个正整数T,表示测试数据的组数。

    接下来是T行,每行包括四个正整数n,k,i,j,其中n∈{4,6,8},表示正多面体的种类,i为起点的编号,j为终点的编号,k为步数(k<=10^18)

Output
    输出T行,每行输出一个整数,表示方法数。(记得要取余哦~)
Sample Input
3
6 1 8 4
6 2 3 1
8 3 2 4
Sample Output
1
2
12
Hint

第二组样例,有3->2->1与3->4->1两种方法

第三组样例,有2->1->4、2->3->4、2->5->4、2->6->4、2->1->3->4、2->1->5->4、2->3->1->4、2->3->6->4、2->5->1->4、2->5->6->4、2->6->3->4、2->6->5->4这12种方法

Source
mathlover
Manager
mathlover


题意明显,思路快速幂,不过得分三种情况来构造操作矩阵,构造方法全部一样。
例如对于四面体的时候假设在K步能够走到1点 Fi(k)代表第K步到i点的放法数则F1(k)=F2(k-1)+F3(k-1)+F4(k-1)说明第K-1步的时候必然在2 3 4 点 那么也就是在k-1步时2 3
 4点的放法数相加,对于六面体,八面体也根据顶点的个数和到达的情况来构造矩阵,然后就这么写了,而且写的很恶心。。后来样例都没过- -结果发现这题是求K步之内到达的方法数。。直接哭瞎,一开始以为要继续构造K个sumk用来记录每种情况的和,后来大湿提醒我,只要多加终点那一维的情况就好了,然后顿悟了,然后敲了一下,过了。。。好累下午做了CF晚上又做了这个,早上还打了羽毛球,快累晕过去了。。。 赶脚状态不是很好啊TVT。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const long long mod=1000000007;
long long n,k,s,e;

struct juzhen {
long long m[10][10];
};

juzhen  mut(juzhen a,juzhen b)
{
    juzhen ans;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            ans.m[i][j]=0;
            for(int k=1;k<=n;k++)
            {
                ans.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
                ans.m[i][j]%=mod;
            }
        }
    }


    return ans;
}

juzhen pow(juzhen a,long long p)
{
    juzhen ans;
    memset(ans.m,0,sizeof(ans.m));
    for(int i=1;i<=n;i++)
    {
        ans.m[i][i]=1;
    }
    while(p)
    {
        if(p%2==0)
        {
            a=mut(a,a);
            p/=2;
        }
        else
        {
            ans=mut(ans,a);
            p--;
        }
    }
    return ans;
}

int main()
{

    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>k>>s>>e;
         juzhen ans;
        if(n==4)
        {

            memset(ans.m,0,sizeof(ans.m));
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(i==j) ans.m[i][j]=0;
                    else ans.m[i][j]=1;
                }
            }

        }
        else if(n==6)
        {
            n=8;

            memset(ans.m,0,sizeof(ans.m));
            ans.m[1][2]=ans.m[1][4]=ans.m[1][5]=1;
            ans.m[2][1]=ans.m[2][3]=ans.m[2][6]=1;
            ans.m[3][2]=ans.m[3][4]=ans.m[3][7]=1;
            ans.m[4][1]=ans.m[4][3]=ans.m[4][8]=1;
            ans.m[5][1]=ans.m[5][6]=ans.m[5][8]=1;
            ans.m[6][2]=ans.m[6][5]=ans.m[6][7]=1;
            ans.m[7][3]=ans.m[7][6]=ans.m[7][8]=1;
            ans.m[8][4]=ans.m[8][5]=ans.m[8][7]=1;




        }
        else if(n==8)
        {
            n=6;

             memset(ans.m,0,sizeof(ans.m));
            ans.m[1][2]=ans.m[1][3]=ans.m[1][4]=ans.m[1][5]=1;
            ans.m[2][1]=ans.m[2][3]=ans.m[2][5]=ans.m[2][6]=1;
            ans.m[3][1]=ans.m[3][2]=ans.m[3][4]=ans.m[3][6]=1;
            ans.m[4][1]=ans.m[4][3]=ans.m[4][5]=ans.m[4][6]=1;
            ans.m[5][1]=ans.m[5][2]=ans.m[5][4]=ans.m[5][6]=1;
            ans.m[6][2]=ans.m[6][3]=ans.m[6][4]=ans.m[6][5]=1;
        }
        juzhen b;
        memset(b.m,0,sizeof(b.m));
        b.m[s][1]=1;//0步的时候就是原地不动的方法数为1,其余均为0,否则状态枚举又能枚举哭你。。。
        n++;
        for(int i=1;i<n;i++)
            ans.m[n][i]=ans.m[e][i];//多加一维记录终点的情况
            ans.m[n][n]=1;
            b=mut(pow(ans,k),b);
            cout<<b.m[n][1]<<endl;

    }
    return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值