hdu 6395 Sequence 分块+矩阵快速幂

Problem Description

Let us define a sequence as below
 

⎧⎩⎨⎪⎪⎪⎪⎪⎪F1F2Fn===ABC⋅Fn−2+D⋅Fn−1+⌊Pn⌋



  Your job is simple, for each task, you should output Fn module 109+7.

Input

The first line has only one integer T, indicates the number of tasks.

Then, for the next T lines, each line consists of 6 integers, A , B, C, D, P, n.

1≤T≤200≤A,B,C,D≤1091≤P,n≤109

Sample Input

 

2 3 3 2 1 3 5 3 2 2 2 1 4

Sample Output

 

36 24

加上⌊P/n⌋就需要分块讨论使用矩阵快速幂。。

若P=20,当前取值为  i=11,则j=P/(P/i)=20;则区间[11,20]是共同的p/i

这个题需要考虑区间范围最大只能到n   因此 j=min(n,p/(p/i));

知道区间的范围,用矩阵快速幂就能求解。

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<deque>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const int M = 1e5 + 10;
int t;
int n,k;
struct node
{
    int id;
    ll num;
}a[6][M],b[6][M];
ll ans[6];
int kp[6];
int vis[M];
bool cmp(node a,node b)
{
    return a.num<b.num;
}
namespace In  {
# define In_Len 2000000
    static std :: streambuf *fb ( std :: cin.rdbuf ( ) ) ;
    static char buf [In_Len], *ss ( 0 ), *tt ( 0 ) ;
# define pick( )  ( (ss == tt) ? ( tt = buf + fb -> sgetn ( ss = buf, In_Len ), ((ss == tt) ? -1 : *(ss ++)) ) :*(ss ++) )

    inline char getc ( )  {  register char c; while ( isspace ( c = pick ( ) ) ) ;  return c ;  }

    inline int read ( )  {
        register int x, c ;
        bool opt ( 1 ) ;
        while ( isspace ( c = pick ( ) ) && ( c ^ -1 ) ) ;
        if ( c == 45 )  c = pick ( ), opt = 0 ;
        for ( x = -48 + c ; isdigit ( c = pick ( ) ) ; ( x *= 10 ) += c - 48 ) ;
        return opt ? x : -x ;
    }
# undef pick
# undef In_Len
}
using namespace In;
namespace Out  {
# define Out_Len 2000000
    std :: streambuf *fb ( std :: cout.rdbuf ( ) ) ;
    char buf [Out_Len], *ss ( buf ), *tt ( buf + Out_Len ) ;
# define echo( c )  ( (ss == tt) ? ( fb -> sputn ( ss = buf, Out_Len ), *ss ++ = c ) : ( *ss ++ = c ) )
    inline void putc ( char c )  {  echo ( c ) ;  }

    inline void print ( register int x )  {
        static int st [30], tp ( 0 ) ;
        if ( ! x )  {  echo ( 48 ) ; return ;  }
        if ( x < 0 )  {  echo ( 45 ) ; x = -x ;  }
        while ( x ) st [++ tp] = x % 10 | 48, x /= 10 ;
        while ( tp )  {  echo ( st [tp] ) ; -- tp ;  }
    }

    inline void flush ( )  {  fb -> sputn ( buf, ss - buf ) ;  }

# undef echo
# undef Out_Len
}
using namespace Out;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        n=read();
        k=read();
        //scanf("%d%d",&n,&k);
        for(int i=0;i<k;i++)
            ans[i]=read();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<k;j++)
            {
                a[j][i].num=read();
                a[j][i].id=i;
            }
            for(int j=0;j<k;j++)
            {
                b[j][i].num=read();
                b[j][i].id=i;
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=0;i<k;i++)
            sort(a[i],a[i]+n,cmp);
        int cnt=0;
        memset(kp,0,sizeof(kp));
        while(1)
        {
            int ok=cnt;
            for(int i=0;i<k;i++)
            {
                while(kp[i]<n && a[i][kp[i]].num<=ans[i])
                {
                    vis[a[i][kp[i]].id]++;
                    if(vis[a[i][kp[i]].id]==k)
                    {
                        cnt++;
                        for(int kk=0;kk<k;kk++)
                            ans[kk]+=b[kk][a[i][kp[i]].id].num;
                    }
                    kp[i]++;
                }
            }
            if(ok==cnt)
                break;
        }
        printf("%d\n",cnt);
        for(int i=0;i<k;i++)
        {
            printf("%lld%c",ans[i],i==k-1?'\n':' ');
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liluoyu_1016/article/details/81774907
今日推荐