UOJ Logo zhouzixuan的博客

博客

bzoj 3286: Fibonacci矩阵

2016-02-16 16:55:45 By zhouzixuan
【题目描述】:

【题目解法】:
    裸的矩阵乘法,由于n m比较大,我又不知道能不能用femat小定理,所以我们直接硬上十进制快速幂辣
    然后就被卡常数了QwQ
    算了TAT,手动矩阵转移,我们发现3*3里面有一行的值是不会变的,我们可以手动转移其它6个值
    还是TLE?我上Contest Hunter上交了一发,2s+AC?
    大新闻:bzoj没有Contest Hunter快?(大雾弥漫)
    然后将int改成longlong,去掉一堆%P总算是10s+A掉了TAT
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1000005;
const long long maxmod=2012182013;
struct node
{
    long long a1,a2,a3;
    long long a4,a5,a6;
    //         0, 0, 1
    inline void clear() {a1=a2=a3=a4=a5=a6=0;}
    inline void init() {clear(); a1=a5=1;}
    inline node operator * (const node &a)
    {
        node b;
        b.a1=(a1*a.a1+a2*a.a4)%maxmod;
        b.a2=(a1*a.a2+a2*a.a5)%maxmod;
        b.a3=(a1*a.a3+a2*a.a6+a3)%maxmod;
        b.a4=(a4*a.a1+a5*a.a4)%maxmod;
        b.a5=(a4*a.a2+a5*a.a5)%maxmod;
        b.a6=(a4*a.a3+a5*a.a6+a6)%maxmod;
        return b;
    }
};
struct Node {int a[N],len;} n,m;
int a,b,c,d,e,f; node ans,fac[10]; Node tmp;
inline long long GetInt()
{
    long long x=0; char c=getchar();
    while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
    while ((c>='0')&&(c<='9')) x=(x*10+(long long)(c-'0'))%maxmod,c=getchar();
    return x;
}
void init()
{
    char ch=getchar();
    for (; (ch<'0')||(ch>'9'); ch=getchar());
    for (n.len=0; (ch>='0')&&(ch<='9'); ch=getchar()) n.a[++n.len]=ch-'0';
    for (; (ch<'0')||(ch>'9'); ch=getchar());
    for (m.len=0; (ch>='0')&&(ch<='9'); ch=getchar()) m.a[++m.len]=ch-'0';
    for (int i=1; i<=n.len/2; i++) swap(n.a[i],n.a[n.len-i+1]);
    for (int i=1; i<=m.len/2; i++) swap(m.a[i],m.a[m.len-i+1]);
    a=GetInt(); b=GetInt(); c=GetInt(); d=GetInt(); e=GetInt(); f=GetInt();
}
inline void sub()
{
    tmp.a[1]--;
    for (int i=1; (i<=tmp.len)&&(tmp.a[i]<0); i++) tmp.a[i+1]--,tmp.a[i]+=10;
    for (; (tmp.len>1)&&(tmp.a[tmp.len]==0); tmp.len--);
}
inline node Mul(node a)
{
    int b=10; node nowans; nowans.init();
    for (;b;b/=2,a=a*a) if (b%2==1) nowans=nowans*a;
    return nowans;
}
inline node calc(node a,Node b)
{
    node nowans; nowans.init(); fac[0].init();
    for (int i=1; i<=9; i++) fac[i]=fac[i-1]*a;
    for (int i=b.len; i>=1; i--) nowans=Mul(nowans)*fac[b.a[i]];
    return nowans;
}
void solve()
{
    ans.init();
    tmp.len=m.len; for (int i=1; i<=m.len; i++) tmp.a[i]=m.a[i]; sub(); sub();
    ans=calc((node){b,a,c,1,0,0},tmp); node nowans=ans;
    ans=ans*(node){e,d,f,1,0,0}*(node){e,d,f,1,0,0};
    tmp.len=n.len; for (int i=1; i<=n.len; i++) tmp.a[i]=n.a[i]; sub();
    ans=calc(ans,tmp); ans=ans*nowans;
    printf("%lld\n",((long long)ans.a1+(long long)ans.a2+(long long)ans.a3)%maxmod);
}
int main()
{
    init();
    solve();
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。