题解 微信步数
题解 微信步数
题目链接
假装更好的阅读体验
如果
题目分析
如果将每一维度都合在一起考虑,复杂度貌似无论如何都需要带上一个
对于维度
对于某一维度
我们需要求的东西是:
直接求出所有的
要拿更高的分数,需要进一步观察
并且上面这个序列是排好序的,有
由于
需要注意的是
中间重复着的若干轮数列之间的
假设重复的轮数为
令:
那么要求的就是:
如何求
直接
如何求
最后的
如果每次都做一次
由于每次我们只会更改某一个位置
如果算上所有操作,总时间复杂度就是
总感觉自己把挺简单的一个东西讲得好复杂啊。
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ch() getchar()
#define pc(x) putchar(x)
template<typename T>void read(T&x){
static char c;static int f;
for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
static char q[64];int cnt=0;
if(x==0)return pc('0'),void();
if(x<0)pc('-'),x=-x;
while(x)q[cnt++]=x%10+'0',x/=10;
while(cnt--)pc(q[cnt]);
}
const int mod=1000000007,maxn=500006,maxk=12;
int mo(const int x){
return x>=mod?x-mod:x;
}
int power(int a,int x){
int re=1;
while(x){
if(x&1)re=1ll*re*a%mod;
a=1ll*a*a%mod,x>>=1;
}
return re;
}
int cnto[maxk][maxn],cntr[maxk][maxn];
int pos[maxk],w[maxk];
int ABS(int x){
return x<0?-x:x;
}
int num[maxk][maxn],p[maxk],pn[maxk];
int sum[maxk][maxn],s[maxk],cn[maxk];
int _s[maxk][maxk],f[maxk];
int dp[maxk];
void chkmin(int&x,int y){
x=min(x,y);
}
int main(){
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
int n,k;read(n),read(k);
for(int i=1;i<=k;++i)read(w[i]);
memset(cnto,0x3f,sizeof cnto);
memset(cntr,0x3f,sizeof cntr);
for(int i=1;i<=n;++i){
int c,d;read(c),read(d);pos[c]+=d;
if(pos[c]<0&& -pos[c]<=w[c])chkmin(cnto[c][-pos[c]],i);
if(pos[c]>0&&w[c]-pos[c]+1>=1 )chkmin(cntr[c][ pos[c]],i);
}
int ok=true,rd=0x3f3f3f3f;
for(int i=1;i<=k;++i){
int no=1,nr=1;
while(cnto[i][no]<0x3f3f3f3f)++no;--no;
while(cntr[i][nr]<0x3f3f3f3f)++nr;--nr;
s[i]=ABS(pos[i]);
if(no+nr>=w[i]){
int l=1,r=w[i];
int vl=min(cnto[i][l],cntr[i][w[i]-l+1]),
vr=min(cnto[i][r],cntr[i][w[i]-r+1]);
while(l<=r){
if(vl<vr)num[i][++p[i]]=vl,++l,vl=min(cnto[i][l],cntr[i][w[i]-l+1]);
else num[i][++p[i]]=vr,--r,vr=min(cnto[i][r],cntr[i][w[i]-r+1]);
}
for(int j=1;j<=s[i];++j)
sum[i][j]=0x3f3f3f3f;
ok=false;rd=0;
}
else{
int l=1,r=1;
while(l<=no||r<=nr){
if(r>nr||(l<=no&&cnto[i][l]<cntr[i][r]))
num[i][++p[i]]=cnto[i][l],++l;
else
num[i][++p[i]]=cntr[i][r],++r;
}
if(pos[i]>0){
for(int j=1;j<=s[i];++j)
sum[i][j]=cntr[i][nr-s[i]+j];
}
if(pos[i]<0){
for(int j=1;j<=s[i];++j)
sum[i][j]=cnto[i][no-s[i]+j];
}
}
if(s[i]>0){
ok=false;
rd=min(rd,(w[i]-p[i])/s[i]);
}
}
if(ok)return puts("-1"),0;
f[0]=rd;_s[0][0]=1;
for(int i=1;i<=k;++i){
_s[i][0]=0;
for(int j=1;j<=i;++j)
_s[i][j]=mo(_s[i-1][j-1]+mo(mod-1ll*(i-1)*_s[i-1][j]%mod));
f[i]=1;int tp=false;
for(int j=0;j<=i;++j){
if((rd-j)%(i+1)==0&&!tp)
f[i]=1ll*f[i]*((rd-j)/(i+1))%mod,tp=true;
else
f[i]=1ll*f[i]*(rd-j)%mod;
}
for(int j=0;j<i;++j)
f[i]=mo(f[i]+mo(mod-1ll*f[j]*_s[i][j]%mod));
}
for(int i=1;i<=k;i+=2)
f[i]=mo(mod-f[i]);
int ans=0;
int all=1;
for(int i=1;i<=k;++i)
all=1ll*all*w[i]%mod;
int pre=0;
while("Imakf ak ioi"){
int mn=0x3f3f3f3f,mp=0;
for(int i=1;i<=k;++i)
if(pn[i]<p[i]&&num[i][pn[i]+1]<mn)
mn=num[mp=i][pn[i]+1];
if(!all||mn>=0x3f3f3f3f){
ans=mo(ans+1ll*(n-pre)*all%mod);
pre=n;break;
}
ans=mo(ans+1ll*(mn-pre)*all%mod);
all=1ll*all*power(w[mp]-pn[mp],mod-2)%mod;
++pn[mp];all=1ll*all*(w[mp]-pn[mp])%mod;
pre=mn;
}
dp[0]=1;
for(int i=1;i<=k;++i){
cn[i]=w[i]-p[i];pn[i]=0;
for(int j=i;j>=1;--j)
dp[j]=mo(1ll*dp[j]*s[i]%mod+1ll*dp[j-1]*cn[i]%mod);
dp[0]=1ll*dp[0]*s[i]%mod;
}
pre=0;
while("Imakf ak ioi"){
int mn=0x3f3f3f3f,mp=0;
for(int i=1;i<=k;++i)
if(pn[i]<s[i]&&sum[i][pn[i]+1]<mn)
mn=sum[mp=i][pn[i]+1];
int add=0;
for(int i=0;i<=k;++i)
add=mo(add+1ll*dp[i]*f[k-i]%mod);
if(mn>=0x3f3f3f3f){
ans=mo(ans+1ll*(n-pre)*add%mod);
pre=n;break;
}
ans=mo(ans+1ll*(mn-pre)*add%mod);
++pn[mp];int I=power(cn[mp],mod-2);
for(int i=k;i>=1;--i)
dp[i]=1ll*mo(mod-1ll*dp[i+1]*s[mp]%mod+dp[i])*I%mod;
--cn[mp];
for(int i=1;i<=k;++i)
dp[i]=mo(1ll*dp[i]*cn[mp]%mod+1ll*dp[i+1]*s[mp]%mod);
pre=mn;
}
all=1;
for(int i=1;i<=k;++i){
w[i]-=(p[i]+rd*s[i]);
all=1ll*all*w[i]%mod;
if(s[i]&&w[i]<=s[i])
s[i]=w[i];
pn[i]=0;
}
pre=0;
while("Imakf ak ioi"){
int mn=0x3f3f3f3f,mp=0;
for(int i=1;i<=k;++i)
if(pn[i]<s[i]&&sum[i][pn[i]+1]<mn)
mn=sum[mp=i][pn[i]+1];
if(!all||mn>=0x3f3f3f3f)break;
ans=mo(ans+1ll*(mn-pre)*all%mod);//puts("ok");
all=1ll*all*power(w[mp]-pn[mp],mod-2)%mod;
++pn[mp];all=1ll*all*(w[mp]-pn[mp])%mod;
pre=mn;
}
write(ans),pc('\n');
return 0;
}