Light oj 1070 - Algebraic Problem

来源:互联网 发布:马甲线软件 编辑:程序博客网 时间:2024/04/30 02:00

题目:Light oj 1070 - Algebraic Problem

思路:这题之前有做过类似的,方法还是构造矩阵,但是这个mod有点挫,mod=2^64 这个值不好取,如果直接做的话,mod=0这样就RuntimeError了

对于用long long 来表示的数字,大小是从-2^64~2^64-1 所以我的运算里如果全部不取模,那么到最后如果是一个正数就直接输出,如果是一个负数的话,相当于整个模是2^65,那么对于进到负数的部分,先乘以-1,然后用2^64减去这个正数得到的就是答案(这个过程我开了一个65位的数组进行模拟的),最后输出当然用unsigned long long 没办法,数据太挫了


#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <iostream>using namespace std;struct Matrix{    long long m[3][3];}E,D;int num[65];int tum[65];long long p,q;void init(){    for(int i=1;i<=2;i++)        for(int j=1;j<=2;j++)            E.m[i][j]=(i==j);}void make(){    D.m[1][1]=p;    D.m[1][2]=-q;    D.m[2][1]=1;    D.m[2][2]=0;}Matrix Multi(Matrix A,Matrix B){    Matrix ans;    for(int i=1;i<=2;i++)        for(int j=1;j<=2;j++)        {            ans.m[i][j]=0;            for(int k=1;k<=2;k++)            {                ans.m[i][j]=(ans.m[i][j]+A.m[i][k]*B.m[k][j]);            }        }    return ans;}Matrix Pow(Matrix A,int k){    Matrix ans=E;    while(k)    {        if(k&1)        {            k--;            ans=Multi(ans,A);        }        else        {            k/=2;            A=Multi(A,A);        }    }    return ans;}int main(){    int t;    scanf("%d",&t);    init();    for(int cases=1;cases<=t;cases++)    {        long long n;        scanf("%lld%lld%lld",&p,&q,&n);        make();        Matrix tmp;        tmp.m[1][1]=p;        tmp.m[2][1]=2;        printf("Case %d: ",cases);        if(n==0)            printf("%lld\n",2);        else        {            Matrix ans=Pow(D,n-1);            Matrix cnt;            for(int i=1;i<=2;i++)            {                cnt.m[i][1]=0;                for(int j=1;j<=2;j++)                    cnt.m[i][1]=(cnt.m[i][1]+ans.m[i][j]*tmp.m[j][1]);            }            if(cnt.m[1][1]>0)                printf("%lld\n",cnt.m[1][1]);            else{                    cnt.m[1][1]*=-1;                for(int i=0;i<=64;i++)                {                    num[i]=0;                    tum[i]=0;                }                num[64]=1;                int tnt=0;                while(cnt.m[1][1])                {                    tum[tnt++]=cnt.m[1][1]%2;                    cnt.m[1][1]/=2;                }                int carry=0;                for(int i=0;i<=64;i++)                {                    num[i]-=tum[i]+carry;                    if(num[i]<0)                    {                        num[i]+=2;                        carry=1;                    }                    else                        carry=0;                }                unsigned long long sy=0;                long long pp=1;                for(int i=0;i<=64;i++)                {                    sy+=num[i]*pp;                    pp*=2;                }                printf("%llu\n",sy);            }        }    }    return 0;}