zoukankan      html  css  js  c++  java
  • 牛客小白月赛6 J 洋灰三角

    J  洋灰三角  

    题目:

    链接:https://www.nowcoder.com/acm/contest/136/J
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

        洋灰是一种建筑材料,常用来筑桥搭建高层建筑,又称,水泥、混凝土。
        WHZ有很多铸造成三角形的洋灰块,他想把这些洋灰三角按照一定的规律放到摆成一排的n个格子里,其中第i个格子放入的洋灰三角数量是前一个格子的k倍再多p个,特殊地,第一个格子里放1个。
        WHZ想知道把这n个格子铺满需要多少洋灰三角。

    输入描述:

    第一行有3个正整数n,k,p。

    输出描述:

    输出一行,一个正整数,表示按照要求铺满n个格子需要多少洋灰三角,由于输出数据过大,你只需要输出答案模1000000007(1e9+7)后的结果即可。
    示例1

    输入

    复制
    3 1 1

    输出

    复制
    6

    说明

    洋灰三角铺法:1 2 3,总计6个
    示例2

    输入

    复制
    3 2 2

    输出

    复制
    15

    说明

    洋灰三角铺法:1 4 10,总计15个
    示例3

    输入

    复制
    3 3 3

    输出

    复制
    28

    说明

    洋灰三角铺法:1 6 21,总计28个

    备注:

    对于100%的测试数据:
    1 ≤ n ≤ 1000000000
    1 ≤ k,p ≤ 1000

    思路:

          矩阵快速幂,但我是直接先求出前几项,再丢进杜教的板子就过了。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <map>
    #include <set>
    #include <cassert>
    #include<bits/stdc++.h>
    
    #define rep(i,a,n) for (ll  i=a;i<n;i++)
    #define per(i,a,n) for (ll  i=n-1;i>=a;i--)
    #define pb push_back
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define fi first
    #define se second
    #define SZ(x) ((ll )(x).size())
    using namespace std;
    typedef long long ll;
    typedef vector<ll > VI;
    
    typedef pair<ll ,ll > PII;
    const ll mod=1000000007;
    ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    // head
    
    ll  _,n;
    namespace linear_seq {
        const ll  N=10010;
        ll res[N],base[N],_c[N],_md[N];
    
        vector<ll > Md;
        void mul(ll *a,ll *b,ll  k) {
            rep(i,0,k+k) _c[i]=0;
            rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
            for (ll  i=k+k-1;i>=k;i--) if (_c[i])
                rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
            rep(i,0,k) a[i]=_c[i];
        }
        ll  solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
    //        prll f("%d
    ",SZ(b));
            ll ans=0,pnt=0;
            ll  k=SZ(a);
            assert(SZ(a)==SZ(b));
            rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
            Md.clear();
            rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
            rep(i,0,k) res[i]=base[i]=0;
            res[0]=1;
            while ((1ll<<pnt)<=n) pnt++;
            for (ll  p=pnt;p>=0;p--) {
                mul(res,res,k);
                if ((n>>p)&1) {
                    for (ll  i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                    rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
                }
            }
            rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
            if (ans<0) ans+=mod;
            return ans;
        }
        VI BM(VI s) {
            VI C(1,1),B(1,1);
            ll  L=0,m=1,b=1;
            rep(n,0,SZ(s)) {
                ll d=0;
                rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
                if (d==0) ++m;
                else if (2*L<=n) {
                    VI T=C;
                    ll c=mod-d*powmod(b,mod-2)%mod;
                    while (SZ(C)<SZ(B)+m) C.pb(0);
                    rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                    L=n+1-L; B=T; b=d; m=1;
                } else {
                    ll c=mod-d*powmod(b,mod-2)%mod;
                    while (SZ(C)<SZ(B)+m) C.pb(0);
                    rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                    ++m;
                }
            }
            return C;
        }
        ll  gao(VI a,ll n) {
            VI c=BM(a);
            c.erase(c.begin());
            rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
            return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
        }
    };
    
    int  main() {
        ll   n, k, p;
        cin>>n>>k>>p;
        ll  sum[120];
        
        ///求出前10项
        sum[1]=1;
        for(ll  i=2;i<=10;i++){
            sum[i]=(sum[i-1]*k%mod+p)%mod;
        }
        for(ll  i=2;i<=10;i++){
            sum[i]=(sum[i-1]+sum[i])%mod;
        }
    
        vector<ll >v;
        for(ll  i=1;i<=10;i++){
            v.push_back(sum[i]);
    
        }
        printf("%lld
    ",linear_seq::gao(v,n-1));
    
    }
  • 相关阅读:
    Win10 UWP Tile Generator
    Win10 BackgroundTask
    UWP Tiles
    UWP Ad
    Win10 build package error collections
    Win10 八步打通 Nuget 发布打包
    Win10 UI入门 pivot multiable DataTemplate
    Win10 UI入门 导航滑动条 求UWP工作
    UWP Control Toolkit Collections 求UWP工作
    Win10 UI入门 SliderRectangle
  • 原文地址:https://www.cnblogs.com/longl/p/9500825.html
Copyright © 2011-2022 走看看