1. 程式人生 > >HDU 6395 靈性優化

HDU 6395 靈性優化

我知道為什麼這道題A的人這麼少了

由於數論分塊的特性

這個塊會在前邊特別密

來後又來個矩陣快速冪

複雜度會很高

還不如一個一個手推

和那個等差數列異或和的優化思想是一樣的

都是對數論分塊的前半部分的優化

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
typedef vector<ll> vec;
typedef vector<vec> mat;
ll Ans[100010];
mat mul(mat& A, mat& B){
    mat C(A.size(), vec(B[0].size()));
    for (ll i = 0; i < A.size(); i++)
        for (ll k = 0; k < B.size(); k++)
            if (A[i][k]) // 對稀疏矩陣的優化
                for (ll j = 0; j < B[0].size(); j++)
                    C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
    return C;
}
mat Pow(mat A, int n){
    mat B(A.size(), vec(A.size()));
    for (ll i = 0; i < A.size(); i++) B[i][i] = 1;
    for (; n; n >>= 1, A = mul(A, A))
        if (n & 1) B = mul(B, A);
    return B;
}
int main(){
    freopen("1.txt","r",stdin);
	int T;
	scanf("%d",&T);
G:
	while(T--){
		ll A,B,C,D,P,n;
		scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&n);
		mat AA(3,vec(3));
		AA[0][0]=D;AA[0][1]=1;AA[0][2]=0;
		AA[1][0]=C;AA[1][1]=0;AA[1][2]=0;
		AA[2][0]=0;AA[2][1]=0;AA[2][2]=1;
		mat BB(1,vec(3));
		mat CC(3,vec(3));
		Ans[1]=A;Ans[2]=B;
		for(int i=3;i<=100000;++i)Ans[i]=(C*Ans[i-2]%mod+D*Ans[i-1%mod]+P/i)%mod;
		if(n<=100000){
			cout<<Ans[n]<<endl;
			goto G;
		}
		BB[0][0]=Ans[100000];BB[0][1]=Ans[99999];BB[0][2]=1;
		for(ll i=100001;i<=P;++i){
			ll x=P/(P/i);
			AA[2][0]=P/i;
			if(n<=x){
				CC=Pow(AA,n-i+1);
				BB=mul(BB,CC);
				cout<<BB[0][0]<<endl;
				goto G;
			}else{
				CC=Pow(AA,x-i+1);
				BB=mul(BB,CC);
			}
			i=x;
		}
		AA[2][0]=0;
		CC=Pow(AA,n-max(P,1ll*2));
		BB=mul(BB,CC);
		cout<<BB[0][0]<<endl;
	}
}