好久没有1Y了呢,而且还是数学题。
思路:
如果没有block,那么除了第一行是之外其余的每一层都是
。
令,
。
相当于求一个模方程。
两边乘以之后求一个离散对数即可。
如果之前一层有block,那么对应这一层的位置就可以放k个(如果这个位置没有block的话),其他位置放k - 1个。
把有block的行存入set,每行每行分情况进行计算。
(码力不精,代码特判较多。)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vl;
typedef vector<vl> vll;
typedef vector<double> vd;
typedef vector<vd> vdd;
typedef pair<int, int> ii;
const ll MOD = 1e8 + 7;
const double eps = 1e-6;
const ll INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
ll n, m, k, b, ans;
set<ll> rec;
map<ll, set<ll> > mp;
ll qp(ll a, ll b){
if(!b)
return 1 % MOD;
if(b & 1)
return a * qp((a * a) % MOD, b >> 1) % MOD;
return qp((a * a) % MOD, b >> 1);
}
ll inv(ll x){
return qp(x, MOD - 2);
}
ll cal(ll a, ll b){
ll m = sqrt(MOD + 0.5);
map<ll, ll> cap;
for(ll i = 0; i < m; i++){
ll cur = qp(a, i);
if(!cap.count(cur))
cap[cur] = i;
}
for(ll i = 0; i <= m; i++){
if(cap.count(b))
return cap[b] + i * m;
b = (b * inv(qp(a, m))) % MOD;
}
return -1;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
int times;
cin >> times;
for(int cas = 1; cas <= times; cas++){
cin >> m >> k >> b >> ans;
rec.clear();
mp.clear();
for(int i = 0; i < b; i++){
ll x, y;
cin >> x >> y;
rec.insert(x);
mp[x].insert(y);
}
ll res = 1;
ll t = qp(k - 1, m);
n = 1;
for(auto u = rec.begin(); u != rec.end(); ++u){
ll i = *u;
if(u == rec.begin()){
if(i > 1)
res = (res * qp(k, m)) % MOD;
if(i - 2 >= 0)
res = (res * qp(t, i - 2)) % MOD;
res = (res * qp(k - (i > 1), m - mp[i].size())) % MOD;
}
else{
auto pre = u;
pre--;
ll j = *pre;
if(j + 1 != i){
res = (res * qp(k - 1, m - mp[j].size())) % MOD;
res = (res * qp(k, mp[j].size())) % MOD;
}
if(i - j - 2 >= 0)
res = (res * qp(t, i - j - 2)) % MOD;
if(j + 1 != i)
res = (res * qp(k - 1, m - mp[i].size())) % MOD;
else{
ll num = mp[i].size();
for(auto v = mp[j].begin(); v != mp[j].end(); ++v)
if(!mp[i].count(*v)){
res = (res * k) % MOD;
num++;
}
res = (res * qp(k - 1, m - num)) % MOD;
}
}
n = i;
}
cout << "Case " << cas << ": ";
if(rec.size()){
if(res == ans){
cout << n << endl;
continue;
}
res = (res * qp(k, mp[n].size())) % MOD;
res = (res * qp(k - 1, m - mp[n].size())) % MOD;
n++;
if(res == ans){
cout << n << endl;
continue;
}
}
else
res = qp(k, m);
res = cal(t, (ans * inv(res)) % MOD);
cout << n + res << endl;
}
cerr << "execute time: " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。