• CF575A. Fibonotci


    题目大意

    题解

    矩乘线段树

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%mod
    #define ll long long
    //#define file
    using namespace std;
    
    struct type{ll x;int s;} b[50001];
    int a[50001],n,m,i,j,k,l,mod;
    ll K,ls,Ls;
    struct mat{ll a[2][2];void clear() {memset(a,0,sizeof(a));}} A,I,s,tr[200001],ans;
    bool cmp(type a,type b) {return a.x<b.x;}
    mat operator * (mat a,mat b)
    {
    	static mat c;
    	int i,j,k;
    	fo(i,0,1)
    	{
    		fo(j,0,1)
    		{
    			c.a[i][j]=0;
    			fo(k,0,1)
    			add(c.a[i][j],a.a[i][k]*b.a[k][j]);
    		}
    	}
    	return c;
    }
    mat qpower(mat a,ll b) {mat ans;ans=I; while (b) {if (b&1) ans=ans*a;a=a*a;b>>=1;} return ans;}
    void mt(int t,int l,int r)
    {
    	int mid=(l+r)/2;
    	tr[t]=I;
    	if (l==r) return;
    	mt(t*2,l,mid),mt(t*2+1,mid+1,r);
    }
    void change(int t,int l,int r,int x,mat s)
    {
    	int mid=(l+r)/2;
    	tr[t]=tr[t]*s;
    	if (l==r) return;
    	
    	if (x<=mid) change(t*2,l,mid,x,s);
    	else change(t*2+1,mid+1,r,x,s);
    }
    mat find(int t,int l,int r,int x,int y)
    {
    	int mid=(l+r)/2;
    	mat ans=I;
    	if (x<=l && r<=y) return tr[t];
    	
    	if (x<=mid) ans=ans*find(t*2,l,mid,x,y);
    	if (mid<y) ans=ans*find(t*2+1,mid+1,r,x,y);
    	return ans;
    }
    mat js(ll x,ll y)
    {
    	if (x==y) return I;
    	return find(1,1,n,x+2,y+1);
    }
    mat Js(ll x,ll y)
    {
    	if (x==y) return I;
    	if (x/n==y/n) return js(x%n,y%n);
    	return ((js(x%n,n-1)*qpower(tr[1],y/n-x/n-1))*A)*js(0,y%n);
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF575A.in","r",stdin);
    	#endif
    	I.a[0][0]=I.a[1][1]=1;
    	
    	scanf("%lld%d",&K,&mod);
    	scanf("%d",&n);
    	fo(i,0,n-1) scanf("%d",&a[i]);
    	mt(1,1,n);
    	fo(i,0,n-1)
    	{
    		s.a[0][0]=0,s.a[0][1]=a[(i+n+n-2)%n];
    		s.a[1][0]=1,s.a[1][1]=a[(i+n-1)%n];
    		if (!i) A=s;
    		change(1,1,n,i+1,s);
    	}
    	ans.a[0][0]=0,ans.a[0][1]=1;
    	if (!K) {printf("0
    ");return 0;}
    	
    	scanf("%d",&m);
    	fo(i,1,m) scanf("%lld%d",&b[i].x,&b[i].s);
    	sort(b+1,b+m+1,cmp);
    	
    	ans=I,ls=1,i=1;
    	while (i<=m && b[i].x<=K && ls<K)
    	{
    		ans=ans*Js(ls,b[i].x),ls=b[i].x,Ls=a[(b[i].x+n-1)%n];
    		while (i<=m && b[i].x<=K && ls==b[i].x && ls<K)
    		{
    			s.a[0][0]=0,s.a[0][1]=Ls;
    			s.a[1][0]=1,s.a[1][1]=b[i].s;
    			ans=ans*s;
    			Ls=b[i].s,++i,++ls;
    		}
    		if (ls<K)
    		{
    			s.a[0][0]=0,s.a[0][1]=b[i-1].s;
    			s.a[1][0]=1,s.a[1][1]=a[ls%n];
    			ans=ans*s,++ls;
    		}
    		else break;
    	}
    	if (ls<K) ans=ans*Js(ls,K);
    	printf("%lld
    ",ans.a[1][1]%mod);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    spring简介
    Thinkphp5 的sesssion在同一个控制器不同的方法无法获取session的原因和对策
    PHP单例模式--典型的三私一公
    10+ 值得收藏的开源后台模板
    PHP中&&与and、||与or的区别
    iview weapp输入组件input事件顺序
    php 获取post方法payload(json)形式参数的方法
    Git pull(拉取),push(上传)命令整理(详细)
    小程序 子组件传值
    php display_errors
  • 原文地址:https://www.cnblogs.com/gmh77/p/13865879.html
Copyright © 2020-2023  润新知