- 思考的过程学到了很多~
- 枚举第i个维度的第j个格子最终出界,预处理出它出界时的步数,需要统计其他格子有多少个的步数大于它。观察到统计的过程中我们并不关注格子的位次,所以可以先排序再进行二分查找。所有步数都是互异的,因此不需要纠结重复的情况。进一步,我们也不关心枚举的格子的位次呀?所以,我们可以按步数从小到大枚举格子,这样就可以通过双指针以O(\(n^2w\))的时间复杂度拿到80分。实现的过程中,需要时刻保证数据的有效性。如l,r都可能会超过w的范围,以及有些格子是不可能出界的等等。
- 朴素处理首尾的格子,用拉格朗日插值优化中间有规律的部分,就可以通过本题
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int w[15],cur[15],l[15],r[15],p[15];
long long s[15][1000005];
unordered_map<int,int>q[15];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,k;
cin>>n>>k;
for(int i=1;i<=k;i++)
{
cin>>w[i];
}
for(int i=1;i<=n;i++)
{
int c,d;
cin>>c>>d;
cur[c]+=d;
l[c]=min(l[c],cur[c]);
r[c]=max(r[c],cur[c]);
if(q[c].find(cur[c])==q[c].end())
{
q[c][cur[c]]=i;
}
}
if(*min_element(cur+1,cur+k+1)==0&&*max_element(cur+1,cur+k+1)==0)
{
cout<<-1<<endl;
return 0;
}
memset(s,0x3f,sizeof(s));
for(int i=1;i<=k;i++)
{
l[i]=-l[i];
for(int j=1;j<=min(l[i],w[i]);j++)
{
s[i][j]=q[i][-j];
}
for(int j=1;j<=min(r[i],w[i]);j++)
{
s[i][w[i]-j+1]=min(s[i][w[i]-j+1],(long long)q[i][j]);
}
if(cur[i]>0&&r[i]<w[i])
{
int L=w[i]-r[i]+1,R=w[i]-r[i]+cur[i];
bool f;
do
{
f=true;
for(int j=L;j<=R;j++)
{
if(j-cur[i]>l[i])
{
s[i][j-cur[i]]=s[i][j]+n;
}
else
{
f=false;
}
}
L-=cur[i];
R-=cur[i];
}while(f);
}
else if(cur[i]<0&&l[i]<w[i])
{
int L=l[i]+cur[i]+1,R=l[i];
bool f;
do
{
f=true;
for(int j=L;j<=R;j++)
{
if(j-cur[i]<=w[i]-r[i])
{
s[i][j-cur[i]]=s[i][j]+n;
}
else
{
f=false;
}
}
L-=cur[i];
R-=cur[i];
}while(f);
}
}
for(int i=1;i<=k;i++)
{
sort(s[i]+1,s[i]+w[i]+1);
}
long long ans=0;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
p[j]=1;
}
for(int j=1;j<=w[i];j++)
{
if(s[i][j]==s[0][0])
{
break;
}
long long sum=s[i][j];
for(int d=1;d<=k;d++)
{
if(i==d)
{
continue;
}
while(s[d][p[d]]<s[i][j])
{
p[d]++;
}
sum=sum*(w[d]-p[d]+1)%mod;
}
ans=(ans+sum)%mod;
}
}
cout<<ans<<endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int w[15],cur[15],l[15],r[15],p[15];
vector<long long>raw[15],s[15];
int len[15],lft[15],tmp[15];
long long h[15];
unordered_map<int,int>q[15];
int y[1000005];
long long S[1000005],jc[1000005];
long long t[1000005];
int power(int n,int p)
{
if(p==0)
{
return 1;
}
long long tmp=power(n,p/2);
if(p%2==1)
{
return tmp*tmp%mod*n%mod;
}
return tmp*tmp%mod;
}
long long lagrange(int m,int k)
{
S[0]=jc[0]=1;
for(int i=1;i<=m;i++)
{
S[i]=S[i-1]*(k-i)%mod;
jc[i]=jc[i-1]*i%mod;
}
t[m+1]=1;
for(int i=m;i>=1;i--)
{
t[i]=t[i+1]*(k-i)%mod;
}
long long ans=0;
for(int i=1;i<=m;i++)
{
long long p=S[i-1]*t[i+1]%mod,q=jc[m-i]*jc[i-1]%mod;
if((m-i)%2==1)
{
q=-q;
}
ans=(ans+y[i]*p%mod*power(q,1000000005)%mod)%mod;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
long long n,k;
cin>>n>>k;
for(int i=1;i<=k;i++)
{
cin>>w[i];
}
for(int i=1;i<=n;i++)
{
int c,d;
cin>>c>>d;
cur[c]+=d;
l[c]=min(l[c],cur[c]);
r[c]=max(r[c],cur[c]);
if(q[c].find(cur[c])==q[c].end())
{
q[c][cur[c]]=i;
}
}
long long minn=INT_MAX;
for(int i=1;i<=k;i++)
{
l[i]=-l[i];
if(l[i]+r[i]>w[i])
{
for(int j=1;j<max(w[i]-r[i]+1,1);j++)
{
s[i].push_back(q[i][-j]);
}
for(int j=max(w[i]-r[i]+1,1);j<=min(l[i],w[i]);j++)
{
s[i].push_back(min(q[i][-j],q[i][w[i]-j+1]));
}
for(int j=min(l[i],w[i])+1;j<=w[i];j++)
{
s[i].push_back(q[i][w[i]-j+1]);
}
}
else
{
len[i]=abs(cur[i]);
if(cur[i]==0)
{
for(int j=w[i]-r[i]+1;j<=w[i];j++)
{
s[i].push_back(q[i][w[i]-j+1]);
}
for(int j=1;j<=l[i];j++)
{
s[i].push_back(q[i][-j]);
}
continue;
}
if(cur[i]>0)
{
for(int j=w[i]-r[i]+1;j<=w[i];j++)
{
s[i].push_back(q[i][w[i]-j+1]);
if(raw[i].size()<len[i])
{
raw[i].push_back(q[i][w[i]-j+1]);
}
}
for(int j=1;j<=l[i];j++)
{
s[i].push_back(q[i][-j]);
}
}
else
{
for(int j=l[i];j>=1;j--)
{
s[i].push_back(q[i][-j]);
if(raw[i].size()<len[i])
{
raw[i].push_back(q[i][-j]);
}
}
for(int j=w[i]-r[i]+1;j<=w[i];j++)
{
s[i].push_back(q[i][w[i]-j+1]);
}
}
reverse(raw[i].begin(),raw[i].end());
lft[i]=(w[i]-l[i]-r[i])%len[i];
h[i]=(w[i]-l[i]-r[i])/len[i];
minn=min(minn,h[i]);
}
}
if(*min_element(cur+1,cur+k+1)==0&&*max_element(cur+1,cur+k+1)==0&&minn==INT_MAX)
{
cout<<-1<<endl;
return 0;
}
for(int i=1;i<=k;i++)
{
sort(s[i].begin(),s[i].end());
if(h[i]==minn)
{
tmp[i]=lft[i];
}
else
{
tmp[i]=len[i];
}
}
long long ans=0;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
p[j]=0;
}
for(int j=0;j<s[i].size();j++)
{
long long sum=s[i][j];
for(int d=1;d<=k;d++)
{
if(i==d)
{
continue;
}
while(p[d]<s[d].size()&&s[d][p[d]]<s[i][j])
{
p[d]++;
}
sum=sum*(w[d]-p[d])%mod;
}
ans=(ans+sum)%mod;
}
}
for(int i=1;i<=k;i++)
{
if(len[i])
{
for(int j=1;j<=k;j++)
{
p[j]=0;
}
for(int j=0;j<tmp[i];j++)
{
long long sum=(raw[i][j]+(minn+1)*n%mod)%mod;
for(int d=1;d<=k;d++)
{
if(i==d)
{
continue;
}
while(p[d]<tmp[d]&&raw[d][p[d]]<raw[i][j])
{
p[d]++;
}
sum=sum*(w[d]-s[d].size()-minn*len[d]-p[d])%mod;
}
ans=(ans+sum)%mod;
}
}
}
for(int i=1;i<=k;i++)
{
if(len[i])
{
for(int j=1;j<=min(minn,k+2);j++)
{
y[j]=y[j-1];
for(int d=1;d<=k;d++)
{
p[d]=0;
}
for(int l=0;l<len[i];l++)
{
long long sum=raw[i][l]+j*n;
for(int d=1;d<=k;d++)
{
if(i==d)
{
continue;
}
while(p[d]<len[d]&&raw[d][p[d]]<raw[i][l])
{
p[d]++;
}
sum=sum*(w[d]-s[d].size()-(j-1)*len[d]-p[d])%mod;
}
y[j]=(y[j]+sum)%mod;
}
}
ans=(ans+lagrange(min(minn,k+2),minn)%mod)%mod;
}
}
cout<<(ans+mod)%mod<<endl;
return 0;
}