2019 ICPC Greater New York Region J - Unicycles (规律+递推+矩阵快速幂)

题目链接


题目大意

给出如图所示那种正 n n n边形然后在中心添加一个点构成,现在需要找到一种 u n i c y c l e unicycle unicycle,定义为第 n n n个图的生成树再连接一条边,问 n n n边形有多少种 u n i c y c l e unicycle unicycle?

解题思路

比赛时没推到规律,空间想象力不强真的没有一点办法,先看题解怎么说吧:
在这里插入图片描述
最难的地方在 M ( i ) M(i) M(i)的基础上添加一个点推 M ( i + 1 ) M(i+1) M(i+1),一旦推出公式,我们得到:

M ( n ) = 1 , 3 , 8 , 21... M(n)=1,3,8,21... M(n)=1,3,8,21...

而斐波那契数列为:

F ( n ) = 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34... F(n)=1,1,2,3,5,8,13,21,34... F(n)=1,1,2,3,5,8,13,21,34...

不难发现对于 M ( i ) M(i) M(i),刚好对应斐波那契数列的 F ( 2 ∗ i ) F(2*i) F(2i),而如果对 M ( n ) M(n) M(n)求和得到前缀和 S ( n ) S(n) S(n)为: 1 , 4 , 12 , 33 , . . . 1,4,12,33,... 1,4,12,33,...
我们不难发现对于每个 S ( i ) S(i) S(i),对于斐波那契数列的 F ( 2 ∗ i + 1 ) − 1 F(2*i+1)-1 F(2i+1)1,那么对于上面的第 n n n个图, a n s = 1 , M ( 1 ) , M ( 2 ) , . . . M ( n − 1 ) ans={ 1,M(1),M(2),...M(n-1) } ans=1,M(1),M(2),...M(n1),而 S ( n − 1 ) = F ( 2 ∗ ( n − 1 ) + 1 ) − 1 S(n-1)=F(2*(n-1)+1)-1 S(n1)=F(2(n1)+1)1,最后再加上 1 1 1,那么最终的答案就是 n ∗ F ( 2 ∗ n − 1 ) n*F(2*n-1) nF(2n1),使用矩阵加速求解即可

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=100007;
const int maxn=2e5+10;
struct Matrix{
    ll matrix[105][105];
};
int n;

Matrix mul(Matrix a,Matrix b){
    Matrix res;
    memset(res.matrix,0,sizeof res.matrix);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    for(int k=1;k<=n;k++){
        res.matrix[i][j]=(res.matrix[i][j]+(a.matrix[i][k]*b.matrix[k][j])%Mod)%Mod;
    }
    return res;
}

Matrix quick_pow(Matrix mx,ll x){
    Matrix ans;
    memset(ans.matrix,0,sizeof ans.matrix);
    for(int i=1;i<=n;i++) ans.matrix[i][i]=1;
    while(x){
        if(x&1) ans=mul(ans,mx);
        mx=mul(mx,mx);
        x>>=1;
    }
    return ans;
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int q;
    Matrix m; n=2;
    m.matrix[1][1]=1,m.matrix[1][2]=1;
    m.matrix[2][1]=1,m.matrix[2][2]=0;
    cin>>q;
    m=quick_pow(m,2*q-1);
    ll ans=m.matrix[2][1];
    cout<<(ans*q)%Mod<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值