CF1924 div1E 题解
NaCly_Fish · · 题解
题目链接
今天随便看到这题,就来口胡一下做法。
首先对于
而对于
尝试对
说是充分大,实际上只要
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
固定
这里
容易发现其只有
这个东西是什么?因为
至于轮廓线上的点怎么求
回来补个代码,实现细节还是稍有点麻烦的:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#define N 2000003
#define ll long long
#define p 1000000007
using namespace std;
int inv[N];
void init(int n){
inv[1] = 1;
for(int i=2;i<=n;++i) inv[i] = (ll)(p-p/i)*inv[p%i]%p;
}
ll ans,k;
int n,m;
vector<int> fr[N>>1];
int st[N],len[N];
inline int F(const int& i,const int& j){
if(j<st[i]||j-st[i]>=fr[i].size()) return 0;
return fr[i][j-st[i]];
}
inline int G(const int& i,const int& j){
return F(i,j)-F(i-1,j)-F(i,j-1)+F(i-1,j-1);
}
int main(){
init(2000000);
int T,px,py;
scanf("%d",&T);
while(T--){
scanf("%d%d%lld",&n,&m,&k);
if((ll)n*m<k){
puts("0");
continue;
}
if((ll)n*m==k){
puts("1");
continue;
}
if(n<m) swap(n,m);
int fir = (k%n==0?k/n:k/n+1);
st[fir-1] = n,ans = 0;
for(int i=fir;i<=m;++i){
st[i] = k%i==0?k/i:k/i+1; // 确定轮廓线在当前行的起始位置
int L = st[i-1]-st[i]+1,sum = 0;
fr[i].resize(L);
if(st[i]<i){ // 利用对称性简化计算
px = i,py = st[i];
fr[i][0] = F(py,px);
}else fr[i][0] = 1;
sum = fr[i][0],ans += G(i,st[i]);
for(int j=1;j<L-1;++j){
fr[i][j] = (ll)sum*inv[i+j+st[i]-2]%p+1;
ans += G(i,j+st[i]);
sum = (sum+fr[i][j])%p;
}
if(L==1) continue;
if(L+st[i]>=i){ // 同样利用对称性
for(int j=1;;++j){
px = L-1+st[i]-st[i-j];
if(px>=fr[i-j].size()||px<0) break;
sum = (sum+fr[i-j][px])%p;
}
fr[i][L-1] = (ll)sum*inv[i+L+st[i]-3]%p+1;
}else{
px = i,py = L-1+st[i];
fr[i][L-1] = fr[py][px-st[py]];
}
ans += G(i,L-1+st[i]);
}
for(int i=fir;i<=m;++i) fr[i].clear();
printf("%lld\n",(ans%p+p)%p);
}
return 0;
}