题目传送门

题目大意: 有一个 kkk 维空间,你要从每一个位置出发走一条循环路线,直到走出边界为止,求走过的总步数。

题解

转化一下,每天走过的总步数,等于每个时刻能走的天数之和。

将 nnn 步看成一轮,那么每轮内在一维上走过的一定是个区间。

设 一轮内,走了第 iii 步后,在第 jjj 维走过的这个区间为 [xj+li,j,xj+ri,j][x_j+l_{i,j},x_j+r_{i,j}][xj​+li,j​,xj​+ri,j​],那么在走到第 iii 步还没有走出边界的点,就需要满足 1−li,j≤xj≤wj−ri,j1-l_{i,j}\leq x_j\leq w_j-r_{i,j}1−li,j​≤xj​≤wj​−ri,j​。

设 一轮后,第 jjj 维的位移为 djd_jdj​。除了第一轮和最后一轮,走过一轮后,第 jjj 维一定有恰好 djd_jdj​ 个位置走出边界,那么第 2+t(t≥0)2+t(t\geq 0)2+t(t≥0) 轮的第 iii 步时,第 jjj 维能用的位置就有 wj−max⁡(rn,j,ri,j+dj)+min(ln,j,li,j+dj)−∣dj∣×tw_j-\max(r_{n,j},r_{i,j}+d_j)+min(l_{n,j},l_{i,j}+d_j)-|d_j|\times twj​−max(rn,j​,ri,j​+dj​)+min(ln,j​,li,j​+dj​)−∣dj​∣×t 个。

乘起来,就得到了第 ttt 轮,第 iii 步时还没有走出边界的起点个数。发现这是个关于 ttt 的 kkk 次多项式,记为 fi(t)=∑j=0kajtjf_i(t)=\sum_{j=0}^k a_jt^jfi​(t)=∑j=0k​aj​tj,不难得出 ttt 的上界,记为 tmaxt_{max}tmax​,那么贡献就是 ∑t=0tmaxfi(t)=∑t=0tmax∑j=0kajtj=∑j=0kaj∑t=0tmaxtj\sum_{t=0}^{t_{max}}f_i(t)=\sum_{t=0}^{t_{max}}\sum_{j=0}^ka_jt^j=\sum_{j=0}^ka_j\sum_{t=0}^{t_{max}}t^j∑t=0tmax​​fi​(t)=∑t=0tmax​​∑j=0k​aj​tj=∑j=0k​aj​∑t=0tmax​​tj。

后面是个自然数幂和,用拉格朗日插值搞搞就行。那么每次需要 k2k^2k2 暴力卷出 fi(t)f_i(t)fi​(t),时间复杂度就是 O(nk2)O(nk^2)O(nk2)。

以及第 111 轮和第 tmax+1t_{max}+1tmax​+1 轮要单独计算,用那个将每一维可用起点数乘起来的做法算即可。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mod 1000000007int n,k,w[11],ans=0;
int d[11];
int l[500010][11],r[500010][11];
void add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
void dec(int &x,int y){x=(x-y<0?x-y+mod:x-y);}
struct Poly{int a[11],t;Poly(){t=0;memset(a,0,sizeof(a));}void clear(){t=0;memset(a,0,sizeof(a));}void operator *=(Poly &B){Poly re;re.t=t+B.t;for(int i=0;i<=t;i++)for(int j=0;j<=B.t;j++)add(re.a[i+j],1ll*a[i]*B.a[j]%mod);*this=re;}
}s[11];
int t_max=1e9;
int calc_round_1(){//暴力求解第一轮int re=0;for(int i=1;i<=n;i++){int prod=1;for(int j=1;j<=k;j++)if(w[j]-r[i][j]+l[i][j]>0)prod=1ll*prod*(w[j]-r[i][j]+l[i][j])%mod;else {prod=0;break;}add(re,prod);}return re;
}
int calc_round_t_max_and_1(){//暴力求解最后一轮int re=0;for(int i=1;i<=n;i++){int prod=1;for(int j=1;j<=k;j++){int p=w[j]-max(r[n][j],r[i][j]+d[j])+min(l[n][j],l[i][j]+d[j])-(t_max+1)*abs(d[j]);if(p>0)prod=1ll*prod*p%mod;else {prod=0;break;}}add(re,prod);}return re;
}
int ksm(int x,int y){int re=1;for(;(y&1?re=1ll*re*x%mod:0),y;y>>=1,x=1ll*x*x%mod);return re;}
struct Lagrange{//自然数幂和板子int fac[20],inv_fac[20];Lagrange(){}void init(){fac[0]=inv_fac[0]=1;for(int i=1;i<=15;i++)fac[i]=1ll*fac[i-1]*i%mod;inv_fac[15]=ksm(fac[15],mod-2);for(int i=14;i>=1;i--)inv_fac[i]=1ll*inv_fac[i+1]*(i+1)%mod;}int pre[20],suf[20];int calc(int k,int x){if(!k)return x+1;int re=0,sum=0;if(x<=k+2){for(int i=0;i<=x;i++)add(re,ksm(i,k));return re;}pre[0]=1;for(int i=1;i<=k+2;i++)pre[i]=1ll*pre[i-1]*(x-i)%mod;suf[k+3]=1;for(int i=k+2;i>=1;i--)suf[i]=1ll*suf[i+1]*(x-i)%mod;for(int i=1;i<=k+2;i++){add(sum,ksm(i,k));(k+2-i&1?dec:add)(re,1ll*sum*pre[i-1]%mod*suf[i+1]%mod*inv_fac[i-1]%mod*inv_fac[k+2-i]%mod);}return re;}
}Lag;
int cd[20];int main()
{scanf("%d %d",&n,&k);ans=1;for(int i=1;i<=k;i++)scanf("%d",&w[i]),ans=1ll*ans*w[i]%mod;for(int i=1,x,y;i<=n;i++){scanf("%d %d",&x,&y);d[x]+=y;for(int j=1;j<=k;j++)l[i][j]=min(l[i-1][j],d[j]),r[i][j]=max(r[i-1][j],d[j]);}bool tf=false;//判无解for(int i=1;i<=k;i++)if(l[n][i]+r[n][i]>=w[i]||d[i]!=0)tf=true;if(!tf)return puts("-1"),0;for(int i=1;i<=k;i++)//求t_maxif(w[i]-r[n][i]+l[n][i]<=0){t_max=-2;break;}else if(d[i]!=0)t_max=min(t_max,(w[i]-r[n][i]+l[n][i])/abs(d[i])-1);add(ans,calc_round_1());if(t_max>-2)add(ans,calc_round_t_max_and_1());if(t_max>=0){Lag.init();//预处理自然数幂和for(int i=0;i<=k;i++)cd[i]=Lag.calc(i,t_max);for(int i=1;i<=n;i++){for(int j=1;j<=k;j++){s[j].clear();//计算出所有多项式,暴力乘起来s[j].t=d[j]!=0;s[j].a[0]=w[j]-max(r[n][j],r[i][j]+d[j])+min(l[n][j],l[i][j]+d[j]);s[j].a[1]=(mod-abs(d[j]))%mod;if(j>1)s[j]*=s[j-1];}for(int j=0;j<=k;j++)add(ans,1ll*s[k].a[j]*cd[j]%mod);}}printf("%d",ans);
}

NOIp 2020 微信步数 题解相关推荐

  1. 全国 2020 NOIP试题 微信步数(walk)

    微信步数(walk) 时间限制:1000毫秒 内存限制:128MB 题目描述 Description 小 C 喜欢跑步,并且非常喜欢在微信步数排行榜上刷榜,为此他制定了一个刷微信步数的计划. 他来到了 ...

  2. [NOIP2020]微信步数

    微信步数 题解 现在才补一年前的题. 首先我们的考虑一个简单的暴力.然而我考场上连这个暴力都没想到 我们将一个点能走多少步转化一下,通过整体来看. 我们考虑走了这一步后还有多少点能够幸存,即没有走出整 ...

  3. NOIP 2020 T1 排水系统(拓扑排序)

    NOIP 2020 T1 排水系统 题解 很显然是拓扑排序,按题意直接模拟复杂度仅仅是 O ( n ) O(n) O(n)的. 但是涉及到分数的加法,通分会爆变量范围吗? 一开始以为最大只是 5 11 ...

  4. 信息学奥赛一本通(C++版)NOIP提高组微信步数

    [题目描述] 小 C 喜欢跑步,并且非常喜欢在微信步数排行榜上刷榜,为此他制定了一个刷微信步数的计划. 他来到了一处空旷的场地,处于该场地中的人可以用 k 维整数坐标 (a1, a2, · · · , ...

  5. 2020微信生态全景运营白皮书:10大热门场景、5大案例剖析.pdf(附下载链接)

    大家好,我是wen wen(微信:sscbg2020),今天给大家分享神策数据11月份发布的白皮书<2020微信生态运营全景解读白皮书:10大热门场景.5大案例剖析>,参与微信生态的伙伴们 ...

  6. 微信公众号数据2019_微信公众号榜单排名,2020微信公众号排名

    微信公众号榜单排名,2020微信公众号排名 公众号排名优化的注意事项及细节今天给大家分享一下,作为微信公众号的排名优化对于大多数人来说都已经知道了有这个渠道的事情,其实很多的新产品及渠道出来以后有不少 ...

  7. 2022-05-05随手更新文章,以及记录一下新的微信步数接口

    本来不想写这个文章的,但好像不写点东西发一下,似乎没法引起大家的注意. 然后最近刚好更新了一下微信步数的API接口,那就顺便也水个文章,露一下脸. 关于微信步数API接口 其实这个也没啥好说的,接口用 ...

  8. android 仿微信账单生成器手机版式,2020微信年度账单生成器

    2020微信年度账单生成器是一款十分有意思的年度账单生成的装杯神器软件,这款软件功能十分的强大且好用,可以生成几百万上千万的微信账单,仅供装杯使用,需要的小伙伴赶紧来下载这款2020微信年度账单生成器 ...

  9. 2020微信设置2小时到账或24小时到账

    2020微信设置2小时到账或24小时到账 进入微信首页,在首页面的菜单栏中点击[我],点击列表中的[支付] 然后在支付页面图示位置点击图标 点击转账到账时间 可设置2小时到账或24小时到账 进入微信首 ...

最新文章

  1. 斯隆奖获得者李婧翌:AI+X并非总是有效,生物数据量小、噪音大,可解释性是关键...
  2. JSP页面退出时清除会话Session
  3. 利用css制作3d图片旋转_练习
  4. php点击按钮查询,管理界面点击按钮打开查询功能
  5. 【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)
  6. Ubuntu下emacs使用搜狗输入法
  7. java exe指的是什么_Java程序的执行过程中用到一套JDK工具,其中java.exe是指( )。
  8. java鼠标中键_java-selenium鼠标键盘操作Actions类和Robot
  9. Ubuntu/Linux下7款轻量级编辑器推荐
  10. Matlab2021a安装教程
  11. 高端计算机教室,惟义楼高端智慧教室!360°高清全景抢先看
  12. Safari 浏览器扩展安装后未显示
  13. linux服务器测网速,linux服务器如何测试网速?
  14. 书摘—吃我吃我:38种改善情绪和恢复精力的神奇食材
  15. 初学graphiql 查询操作
  16. Thread Handler
  17. 收索资源好用的网盘搜索引擎
  18. JS实现轮播图点击切换、按钮切换功能
  19. eclipse中测试java_在Eclipse中使用JUnit进行单元测试
  20. 分子动力学模拟再登顶刊(IF=18.72)

热门文章

  1. C++ string现代写法
  2. jquery触屏幻灯片
  3. C语言100个囚犯和灯泡,一百个囚犯和一个灯泡
  4. BZOJ3527 力
  5. SC-Lego-LOAM解析(上)
  6. S5PV210中断的介绍与配置
  7. python用matplotlib作图时,x轴为时间轴,如何让x轴每隔几个点显示一次?
  8. 适合学生党的蓝牙耳机品牌有哪些?性价比高的无线耳机推荐
  9. numpy学习(五)——文件的保存和读写(np.save()、np.load()、np.savez()、np.savetxt()、np.loadtxt())
  10. 华为手机录制屏幕视频的详细操作