CSES - Putka Open 2020 – 2/5 - Results
Submission details
Task:Torni
Sender:Laakeri
Submission time:2020-09-26 10:36:15 +0300
Language:C++ (C++11)
Status:READY
Result:100
Feedback
groupverdictscore
#1ACCEPTED15
#2ACCEPTED41
#3ACCEPTED44
Test results
testverdicttimegroup
#1ACCEPTED0.01 s1, 2, 3details
#2ACCEPTED0.01 s2, 3details
#3ACCEPTED0.01 s3details

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll powmod(ll a, ll p, ll modd) {
	if (p==0) return 1;
	if (p%2==0) {
		a=powmod(a, p/2, modd);
		return (a*a)%modd;
	}
	return (a*powmod(a, p-1, modd))%modd;
}
ll invp(ll a, ll p) {
	return powmod(a, p - 2, p);
}
vector<ll> solve(vector<ll> S, ll mod) {
	vector<ll> C = {1};
	vector<ll> B = {1};
	ll L = 0;ll m = 1;ll b = 1;ll N = S.size();
	for (ll i = 0; i < N; i++) {
		ll d = S[i];
		for (ll j = 1; j <= L; j++) {
			d += C[j]*S[i - j];d %= mod;
		}
		if (d == 0) {
			m++;
		} else if (2*L <= i) {
			vector<ll> T = C;
			ll a = (invp(b, mod)*d)%mod;
			for (int j=0;j<i+1-2*L;j++) {
				C.push_back(0);
			}
			L=i+1-L;
			for (ll j = m; j <= L; j++) {
				C[j] -= a*B[j - m];C[j] %= mod;
			}
			B = T;b = d;m = 1;
		} else {
			ll a = (invp(b, mod)*d)%mod;
			for (ll j = m; j < m+(int)B.size(); j++) {
				C[j] -= a*B[j - m];C[j] %= mod;
			}
			m++;
		}
	}
	for (ll i = 0; i <= L; i++) {
		C[i] += mod;C[i] %= mod;
	}
	return C;
}
struct LinearRecurrence {
	vector<vector<ll> > mat;
	vector<ll> seq;
	ll mod;
	vector<vector<ll> > mul(vector<vector<ll> > a, vector<vector<ll> > b) {
		int n=a.size();
		vector<vector<ll> > ret(n);
		for (int i=0;i<n;i++){
			ret[i].resize(n);
			for (int j=0;j<n;j++){
				ret[i][j]=0;
				for (int k=0;k<n;k++){
					ret[i][j]+=a[i][k]*b[k][j];
					ret[i][j]%=mod;
				}
			}
		}
		return ret;
	}
	vector<vector<ll> > pot(vector<vector<ll> > m, ll p) {
		if (p==1) return m;
		if (p%2==0) {
			m=pot(m, p/2);
			return mul(m, m);
		}
		else {
			return mul(m, pot(m, p-1));
		}
	}
	ll get(ll index) {
		if (index<(ll)mat.size()) {
			return seq[index];
		}
		vector<vector<ll> > a=pot(mat, index-(ll)mat.size()+1);
		ll v=0;
		for (int i=0;i<(int)mat.size();i++) {
			v+=a[0][i]*seq[(int)mat.size()-i-1];
			v%=mod;
		}
		return v;
	}
	LinearRecurrence(vector<ll> S, ll mod_) {
		seq=S;
		mod=mod_;
		vector<ll> C=solve(S, mod);
		int n=C.size()-1;
		mat.resize(n);
		for (int i=0;i<n;i++) {
			mat[i].resize(n);
		}
		for (int i=0;i<n;i++) {
			mat[0][i]=(mod-C[i+1])%mod;
		}
		for (int i=1;i<n;i++) {
			mat[i][i-1]=1;
		}
	}
};

const ll mod=1e9+7;

ll dp[30][30];

int main(){
	dp[0][0]=1;
	for (int i=0;i<30;i++){
		for (int j=0;j<30;j++){
			if (j==i){
				for (int t=1;i+t<30;t++){
					dp[i+t][j+t]+=dp[i][j];
					dp[i+t][j+t]%=mod;
				}
				for (int t=1;i+t<30;t++){
					dp[i+t][j]+=dp[i][j];
					dp[i+t][j]%=mod;
				}
			} else if (i<j){
				for (int t=1;i+t<30;t++){
					dp[i+t][j]+=dp[i][j];
					dp[i+t][j]%=mod;
				}
			} else {
				for (int t=1;j+t<30;t++){
					dp[i][j+t]+=dp[i][j];
					dp[i][j+t]%=mod;
				}
			}
		}
	}
	vector<ll> s(20);
	for (int i=0;i<20;i++){
		s[i]=dp[i][i];
	}
	LinearRecurrence lr(s, mod);
	int t;
	cin>>t;
	for (int i=0;i<t;i++){
		int x;
		cin>>x;
		cout<<lr.get(x)<<endl;
	}
}

Test details

Test 1

Group: 1, 2, 3

Verdict: ACCEPTED

input
10
1
2
3
4
...

correct output
2
8
34
148
650
...

user output
2
8
34
148
650
...

Test 2

Group: 2, 3

Verdict: ACCEPTED

input
100
1
2
3
4
...

correct output
2
8
34
148
650
...

user output
2
8
34
148
650
...
Truncated

Test 3

Group: 3

Verdict: ACCEPTED

input
100
996306
650655
896240
821967
...

correct output
87350005
606189151
122595036
193572715
227926807
...

user output
87350005
606189151
122595036
193572715
227926807
...
Truncated