QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#266518#4318. 高性能计算导论集群登录密码复杂性策略jzh#TL 212ms35668kbC++237.1kb2023-11-26 15:05:232023-11-26 15:05:24

Judging History

This is the latest submission verdict.

  • [2023-11-26 15:05:24]
  • Judged
  • Verdict: TL
  • Time: 212ms
  • Memory: 35668kb
  • [2023-11-26 15:05:23]
  • Submitted

answer

#include<bits/stdc++.h>
#include <cassert>

using namespace std;

using ll = long long;

constexpr ll P = 1e9 + 7;

const int maxn = 2000;

ll qpow(ll a, ll b) {
	ll ans = 1;
	for(; b; a = a * a % P, b /= 2) {
		if(b&1) ans = ans * a % P;
	}
	return ans;
}

namespace Polynomial {
	using poly = vector<ll>;
	poly operator += (poly &A, poly B) {
		A.resize(max(A.size(), B.size()));
		for(int i = 0 ; i < A.size() ; i ++) {
			if(i<B.size()) A[i] = (A[i] + B[i]) % P;
		}
		return A;
	}
	poly operator + (poly A, poly B) {
		return A += B;
	}
	poly operator -= (poly &A, poly B) {
		A.resize(max(A.size(), B.size()));
		for(int i = 0 ; i < A.size() ; i ++) {
			if(i<B.size()) A[i] = (A[i] - B[i] + P) % P;
		}
		return A;
	}
	poly operator - (poly A, poly B) {
		return A -= B;
	}
	poly operator * (poly A, ll b) {
		for(auto &v: A) v = v * b % P;
		return A;
	}
	poly operator * (poly A, poly B) {
		poly C(A.size() + B.size() - 1);
		for(int i = 0 ; i < A.size() ; i ++) {
			for(int j = 0 ; j < B.size() ; j ++) {
				C[i+j] = (C[i+j] + A[i] * B[j]) % P;
			}
		}
		return C;
	}
	poly operator / (poly A, poly B) {
		int n = A.size(), m = B.size();
		poly ans = {0};

		vector<poly>vec;
		vec.push_back(B);
		for(int i = 1 ; i + m <= n ; i ++) {
			vec.push_back(vec.back() * poly{0, 1});
		}

		for(int i = n-1 ; i >= m-1 ; i --) {
			ans = ans * poly{0, 1};
			ans[0] = (A[i] * qpow(B[m-1], P-2)) % P;
			A -= vec[i-m+1] * ans[0];
		}

		return ans;
	}
	poly operator % (poly A, poly B) {
		A = A - (A/B)*B;
		while(A.size()>1 and A.back()==0) A.pop_back();
		return A;
	}
	poly POW(poly A, int k, poly p) {
		poly ans = {1};
		while(k) {
			if(k%2==1) ans = (ans * A) % p;
			A = A * A % p;
			k /= 2;
		}
		return ans;
	} 
};

using namespace Polynomial;

ll dp[maxn][maxn];


vector<int>BM(const vector<int>&a) {
	vector<int>v, last;
    int k = -1, delta = 0;

    for(int i = 0 ; i < (int)a.size() ; i ++) {
    	int tmp = 0;
    	for(int j = 0 ; j < (int)v.size(); j ++) {
    		tmp = (tmp + (ll)a[i-j-1] * v[j]) % P;
    	}

    	if(a[i]==tmp) continue;

    	if(k<0) {
    		k = i;
    		delta = (a[i] - tmp + P) % P;
    		v = vector<int>(i+1);
    		continue;
    	}

    	vector<int>u = v;
    	int val = (ll)(a[i] - tmp + P) * qpow(delta, P-2) % P;

    	if(v.size()<last.size() + i - k) v.resize(last.size() + i - k);

    	(v[i-k-1]+=val)%=P;

    	for(int j = 0 ; j < (int)last.size() ; j ++) {
    		v[i-k+j] = (v[i-k+j] - (ll)val * last[j]) % P;
    		if(v[i-k+j]<0) v[i-k+j] += P;
    	}

    	if((int)u.size() - i < (int)last.size()-k) {
    		last = u;
    		k = i;
    		delta = a[i] - tmp;
    		if(delta<0) delta += P;
    	}
    }

    for(auto &x: v) x = (P-x) % P;
    v.insert(begin(v), 1);

	return v;
}

struct Aho_Corasick {
	int nxt[maxn][130], fail[maxn];
	bool vis[maxn];
	int root, idx;

	void clear() {
		memset(nxt[0], 0, sizeof(nxt[0]));
		memset(vis, 0, sizeof(vis));
		root = idx = 0;
	}
	int newnode() {
		fail[++idx] = 0; memset(nxt[idx], 0, sizeof(nxt[idx]));
		return idx;
	}
	int insert(int pre, int ch) {
		return nxt[pre][ch]?nxt[pre][ch]:nxt[pre][ch] = newnode();
	}
	void insert(const char *s) {
		//cout << s << endl;
		int now = root;
		for(int i = 0 ; s[i] ; i ++) {
			now = insert(now, s[i]);
		}
		vis[now] = true;
	}
	void build() {
		fail[root] = root;
		queue<int>q;
		for(int i = 0 ; i < 130 ; i ++) if(nxt[0][i]) q.push(nxt[0][i]);
		while(!q.empty()) {
			int h = q.front(); q.pop();
			for(int i = 0 ; i < 130 ; i ++) {
				if(!nxt[h][i]) {
					nxt[h][i] = nxt[fail[h]][i];
				}
				else{
					int tmp = nxt[h][i];
					fail[tmp] = nxt[fail[h]][i];
					q.push(tmp);
				}
			}
		}
	}

	ll calc(int l, int r, const vector<int>sigma) {
		memset(dp, 0, sizeof(dp));
		dp[0][root] = 1;

		int n = idx + 10;
		for(int i = 0 ; i < n ; i ++) {
			for(int st = 0 ; st <= idx ; st ++) {
				if(!dp[i][st] or vis[st]) continue;
				for(auto &ch: sigma) {
					if(vis[nxt[st][ch]]) continue;
					(dp[i+1][nxt[st][ch]] += dp[i][st]) %= P;
				}
			}
		}

		vector<int>vec(n);
		for(int i = 0 ; i < n ; i ++) {
			for(int st = 0 ; st <= idx ; st ++) {
				vec[i] = (vec[i] + dp[i][st]) % P;
			}
		}

		auto p = BM(vec);
		auto temp = poly(begin(p), end(p)) * poly{-1, 1};

		auto res1 = POW({0, 1}, r+1, temp);
		auto res2 = POW({0, 1}, l, temp);

		//for(auto &v: res1) cout << v << ' '; cout << endl;
		//for(auto &v: res2) cout << v << ' '; cout << endl;

		auto res = (res1-res2) / poly{-1, 1};

		ll ans = 0;
		for(int i = 0 ; i < res.size() ; i ++) {
			ans = (ans + res[i] * vec[i]) % P;
		}
		return ans;
	}
}acam;

void solve() {
	/*vector<int>a = {3, 4, 6, 10, 18, 34};

	auto vec = BM(a);
	for(auto &v: vec) cout << v << ' '; cout << endl;*/

	ll l, r, a, b; cin >> l >> r >> a >> b;

	auto add_num = [&]() {
		for(char ch = '0' ; ch <= '9' ; ch ++) {
			string temp(a, ch);
			acam.insert(temp.c_str());
		}
		for(char ch = '0' ; ch + b - 1 <= '9' ; ch ++) {
			string temp;
			for(char t = ch ; t <= ch + b - 1 ; t ++) temp += t;
			acam.insert(temp.c_str());
		}
		for(char ch = '9' ; ch - b + 1 >= '0' ; ch --) {
			string temp;
			for(char t = ch ; t >= ch - b + 1 ; t --) temp += t;
			acam.insert(temp.c_str());
		}
	};
	auto add_ch = [&]() {
		for(char ch = 'a' ; ch <= 'z' ; ch ++) {
			string temp(a, ch);
			acam.insert(temp.c_str());
		}
		for(char ch = 'A' ; ch <= 'Z' ; ch ++) {
			string temp(a, ch);
			acam.insert(temp.c_str());
		}
		for(char ch = 'a' ; ch + b - 1 <= 'z' ; ch ++) {
			string temp;
			for(char t = ch ; t <= ch + b - 1 ; t ++) temp += t;
			acam.insert(temp.c_str());
		}
		for(char ch = 'z' ; ch - b + 1 >= 'a' ; ch --) {
			string temp;
			for(char t = ch ; t >= ch - b + 1 ; t --) temp += t;
			acam.insert(temp.c_str());
		}
		for(char ch = 'A' ; ch + b - a <= 'Z' ; ch ++) {
			string temp;
			for(char t = ch ; t <= ch + b - 1 ; t ++) temp += t;
			acam.insert(temp.c_str());
		}
		for(char ch = 'Z' ; ch - b + 1 >= 'A' ; ch --) {
			string temp;
			for(char t = ch ; t >= ch - b + 1 ; t --) temp += t;
			acam.insert(temp.c_str());
		}
	};

	ll ans = 0;

	// all
	acam.clear();
	add_num();
	add_ch();
	acam.build();

	vector<int>sigma;
	for(char ch = '0' ; ch <= '9' ; ch ++) sigma.push_back(ch);
	for(char ch = 'a' ; ch <= 'z' ; ch ++) sigma.push_back(ch);
	for(char ch = 'A' ; ch <= 'Z' ; ch ++) sigma.push_back(ch);
	ans = (ans + acam.calc(l, r, sigma)) % P;

	// only number
	acam.clear();
	add_num();
	acam.build();

	sigma = {};
	for(char ch = '0' ; ch <= '9' ; ch ++) sigma.push_back(ch);
	ans = (ans - acam.calc(l, r, sigma)) % P;

	// only char
	acam.clear();
	add_ch();
	acam.build();

	sigma = {};
	for(char ch = 'a' ; ch <= 'z' ; ch ++) sigma.push_back(ch);
	for(char ch = 'A' ; ch <= 'Z' ; ch ++) sigma.push_back(ch);
	ans = (ans - acam.calc(l, r, sigma)) % P;

	cout << (ans + P) % P << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	solve();

	return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 212ms
memory: 35668kb

input:

1 1 6 14

output:

0

result:

ok single line: '0'

Test #2:

score: -100
Time Limit Exceeded

input:

107140316 406944816 6 13

output:


result: