\(T1\ Beauty\)





\(T2\ Jump\)

考场上一开始想的是树套树,然后我看到了\(128MB,\)好

于是乎附上\(56pts\ MLE\)代码在空间\(512MB\)可以获得\(84pts,\)时限调到\(8s,\)可以\(AC\)

#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
struct City
{
int x,y;
}cy[MAXN];
struct Link
{
int val,l,r,u,d;
};
vector<Link>rd[MAXN];
int dis[MAXN],ID1,ID2,rt,n,m,h,w;
bool vis[MAXN];
struct Tr1
{
int l,r,ls,rs;
int rt;
}tr1[MAXN<<3];
struct node
{
int l,r,ls,rs;
vector<int>Get;
}tr2[MAXN<<3];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void Query2(int now,int L,int R,int l,int r,int st,int val)
{
if(!now) return ;
if(L>=l&&R<=r)
{
for(int i=0;i<tr2[now].Get.size();i++)
{
int y=tr2[now].Get[i];
if(dis[y]>dis[st]+val)
{
dis[y]=dis[st]+val;
q.push(make_pair(dis[y],y));
}
}
return ;
}
int mid=(L+R)>>1;
if(l<=mid) Query2(tr2[now].ls,L,mid,l,r,st,val);
if(r>mid) Query2(tr2[now].rs,mid+1,R,l,r,st,val);
}
void Query1(int now,int L,int R,int l,int r,int u,int d,int st,int val)
{
if(!now) return ;
// cout<<"Ins1: "<<st<<" "<<L<<" "<<R<<"\n";
if(L>=l&&R<=r)
{
Query2(tr1[now].rt,1,w,u,d,st,val);
return ;
}
int mid=(L+R)>>1;
if(l<=mid) Query1(tr1[now].ls,L,mid,l,r,u,d,st,val);
if(r>mid) Query1(tr1[now].rs,mid+1,R,l,r,u,d,st,val);
}
void dij()
{
memset(dis,0x3f,sizeof(dis));
q.push(make_pair(dis[1],1));
dis[1]=0;
while(q.size())
{
int now=q.top().second;
q.pop();
if(vis[now]) continue;
vis[now]=true;
for(int i=0;i<rd[now].size();i++)
{
int val=rd[now][i].val;
int l=rd[now][i].l;
int r=rd[now][i].r;
int u=rd[now][i].u;
int d=rd[now][i].d;
Query1(rt,1,h,l,r,u,d,now,val);
continue;
for(int j=1;j<=n;j++)
{
if(cy[j].x>=l&&cy[j].x<=r&&cy[j].y>=u&&cy[j].y<=d)
{
if(dis[j]>dis[now]+val)
{
dis[j]=dis[now]+val;
q.push(make_pair(dis[j],j));
continue;
}
}
}
}
}
}
void Insert2(int &now,int l,int r,int y,int id)
{
if(l>y||r<y) return ;
if(!now) now=++ID2;
// cout<<"Ins2: "<<now<<" "<<l<<" "<<r<<" "<<y<<" "<<id<<"\n";
tr2[now].Get.push_back(id);
if(l==r) return ;
int mid=(l+r)>>1;
Insert2(tr2[now].ls,l,mid,y,id);
Insert2(tr2[now].rs,mid+1,r,y,id);
}
void Insert1(int &now,int l,int r,int x,int y,int id)
{
if(l>x||r<x) return ;
if(!now) now=++ID1;
// cout<<"Ins1: "<<l<<" "<<r<<" "<<x<<"\n";
Insert2(tr1[now].rt,1,w,y,id);
if(l==r) return ;
int mid=(l+r)>>1;
Insert1(tr1[now].ls,l,mid,x,y,id);
Insert1(tr1[now].rs,mid+1,r,x,y,id);
}
int main()
{
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&h,&w);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&cy[i].x,&cy[i].y);
Insert1(rt,1,h,cy[i].x,cy[i].y,i);
}
for(int i=1,l,r,u,d,cs,poz;i<=m;i++)
{
scanf("%d%d%d%d%d%d",&poz,&cs,&l,&r,&u,&d);
rd[poz].push_back((Link){cs,l,r,u,d});
}
dij();
for(int i=2;i<=n;i++)
{
printf("%d\n",dis[i]);
}
}

我把内层线段树用\(set\)代替,好,只有\(60pts\)是怎么会是呢?

附上\(60pts\ TLE\)代码,常数真的很大

#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define MAXN 260005
using namespace std;
template<class T>
T Read()
{
T x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^'0');
ch=getchar();
}
return x*f;
}
int (*read)()=Read<int>;
#define read Read<int>
struct Link
{
int val,l,r,u,d;
};
vector<Link>rd[MAXN];
int dis[MAXN],ID1,ID2,rt,n,m,h,w;
bool vis[MAXN];
struct Tr1
{
int ls,rs;
set<pair<int,int> >Get;
}tr1[MAXN<<2];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void Query1(int now,int L,int R,int l,int r,int u,int d,int st,int val)
{
if(!now) return ;
// cout<<"Ins1: "<<st<<" "<<L<<" "<<R<<"\n";
if(L>=l&&R<=r)
{
pair<int,int>Now;
Now=make_pair(u,0);
set<pair<int,int> >::iterator it=tr1[now].Get.lower_bound(Now);
for(;it->first<=d&&it!=tr1[now].Get.end();it++)
{
int y=it->second;
if(dis[y]>dis[st]+val)
{
dis[y]=dis[st]+val;
q.push(make_pair(dis[y],y));
}
}
return ;
}
int mid=(L+R)>>1;
if(l<=mid) Query1(tr1[now].ls,L,mid,l,r,u,d,st,val);
if(r>mid) Query1(tr1[now].rs,mid+1,R,l,r,u,d,st,val);
}
void dij()
{
memset(dis,0x3f,sizeof(dis));
q.push(make_pair(dis[1],1));
dis[1]=0;
while(q.size())
{
int now=q.top().second;
q.pop();
if(vis[now]) continue;
vis[now]=true;
for(int i=0;i<rd[now].size();i++)
{
int val=rd[now][i].val;
int l=rd[now][i].l;
int r=rd[now][i].r;
int u=rd[now][i].u;
int d=rd[now][i].d;
Query1(rt,1,h,l,r,u,d,now,val);
}
}
}
void Insert1(int &now,int l,int r,int x,int y,int id)
{
if(l>x||r<x) return ;
if(!now) now=++ID1;
tr1[now].Get.insert(make_pair(y,id));
if(l==r) return ;
int mid=(l+r)>>1;
Insert1(tr1[now].ls,l,mid,x,y,id);
Insert1(tr1[now].rs,mid+1,r,x,y,id);
}
int main()
{
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&h,&w);
for(int i=1,x,y;i<=n;i++)
{
x=read(); y=read();
Insert1(rt,1,h,x,y,i);
}
for(int i=1,l,r,u,d,cs,poz;i<=m;i++)
{
poz=read(); cs=read(); l=read(); r=read(); u=read(); d=read();
rd[poz].push_back((Link){cs,l,r,u,d});
}
dij();
for(int i=2;i<=n;i++)
{
printf("%d\n",dis[i]);
}
}

加上一些优化,得到外层线段树套\(set\)代码,怎么这个技巧这么\(Nb\)呢?

附上\(100pts\)代码

#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define MAXN 150005
using namespace std;
int rd()
{
int f=1,ans=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
return f*ans;
}
priority_queue<pair<int,int> > que;
set<pair<int,int> >s[MAXN<<2];
int dis[MAXN<<2],vis[MAXN<<2],head[MAXN],cnt;
struct spe
{
int x,y;
}g[MAXN];
struct Segment
{
#define ls (k<<1)
#define rs ((k<<1)|1)
void change(int k,int l,int r,int x,int y,int id)
{
s[k].insert(make_pair(g[id].y,id));
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) change(ls,l,mid,x,y,id);
if(mid<y) change(rs,mid+1,r,x,y,id);
return;
}
void Query(int k,int l,int r,int x,int y,int L,int R,int id)
{
if(x<=l&&r<=y)
{
set<pair<int,int> >:: iterator it;
while(!s[k].empty())
{
it=s[k].lower_bound(make_pair(L,-1));
if(it==s[k].end()||(*it).first>R) break;
int v=(*it).second;
if(dis[v]>dis[id])
{
dis[v]=dis[id];
que.push(make_pair(-dis[v],v));
}
s[k].erase(*it);
}
return;
}
int mid=(l+r)>>1;
if(x<=mid) Query(ls,l,mid,x,y,L,R,id);
if(mid<y) Query(rs,mid+1,r,x,y,L,R,id);
return;
}
}tr;
int n,m,w,h;
struct node
{
int u,v,nex;
}x[MAXN<<1];
struct Spe
{
int be,w,l,r,d,u;
}f[MAXN];
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int main()
{
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
memset(head,-1,sizeof(head));
n=rd(),m=rd(),w=rd(),h=rd();
for(int i=1;i<=n;i++)
{
g[i].x=rd(),g[i].y=rd();
tr.change(1,1,w,g[i].x,g[i].x,i);
}
for(int i=1;i<=m;i++)
{
f[i].be=rd(),f[i].w=rd();
f[i].l=rd(),f[i].r=rd();
f[i].d=rd(),f[i].u=rd();
add(f[i].be,i);
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0;que.push(make_pair(0,1));
while(!que.empty())
{
int xx=que.top().second;que.pop();
if(vis[xx]) continue;
vis[xx]=1;
if(xx>n)
{
tr.Query(1,1,w,f[xx-n].l,f[xx-n].r,f[xx-n].d,f[xx-n].u,xx);
continue;
}
for(int i=head[xx];i!=-1;i=x[i].nex)
{
int v=x[i].v+n;
if(dis[v]>dis[xx]+f[x[i].v].w)
{
dis[v]=dis[xx]+f[x[i].v].w;
que.push(make_pair(-dis[v],v));
}
}
}
for(int i=2;i<=n;i++) printf("%d\n",dis[i]);
return 0;
}

\(T3\ Combination\)

\[\sum_{0\le i\le n,k|i}\binom{n}{i}
\\
=\sum_{0\le i\le n}[k|i]\binom{n}{i}
\]

单位根反演

\[[k|i]=\frac{1}{k}\sum_{j=0}^{k-1}w_k^{i\times j}
\]

反代

\[\sum_{0\le i\le n}\frac{1}{k}\sum_{j=0}^{k-1}w_k^{i\times j}\binom{n}{i}
\\
=\frac{1}{k}\sum_{j=0}^{k-1}\sum_{0\le i\le n}(w_k^j)^i\binom{n}{i}
\]

较为显然的二项式形式

\[\frac{1}{k}\sum_{j=0}^{k-1}(w_k^j+1)^n
\]

在\(\mod=998244353\)​可以直接计算

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 100010
const int p=998244353;
int n,k;
int ksm(int a,int b)
{
int ans=1;
for(;b;b>>=1,a=a*a%p)
if(b&1)ans=ans*a%p;
return ans;
}
int w,wn=1;
int ans;
signed main()
{
cin>>n>>k;
w=ksm(114514,(p-1)/k);
for(int i=0;i<k;i++,wn=wn*w%p)
ans=(ans+ksm(1+wn,n%(p-1)))%p;
ans=ans*ksm(k,p-2)%p;
cout<<ans;
}

我发现我的\(NTT\)真的只是背过的,我连模数意义下的单位根都不熟练

\(w_k=3^{(mod -1)/k}\)

至于\(\mod=998244853\)

可以使用多项式快速幂计算,复杂度\(O(k\log(n)\log(k))\)

然后发现题干中有一句话\(k=2^p\)

设\(const(F(x))=[x^0]F(x)\)

打表发现

\(const((1+w_k^i)^n)=const((1+w_k)^n)\)

证明略

然后下面的式子就很通俗易懂了

而且发现了一个很nb的操作,在mod 998244353时,原根可以写114514!!!

于是乎我们的\(NTT\)可以这么写

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int G=114514,mod=998244353;

原根性质,\(a^{\phi(m)}=1(\mod m)\)

\(k\)次单位根\(a^{(mod-1)/k}\)

然后代码

#include<bits/stdc++.h>
#define mo 998244853
#define base 35000
using namespace std;
const double Pie=acos(-1);
inline long long readl()
{
long long r(0);char in=getchar();while(in<'0'||in>'9')in=getchar();
while(in>='0'&&in<='9')r=(r<<1)+(r<<3)+(in^48),in=getchar();return r;
}
inline int read()
{
int r(0);char in=getchar();while(in<'0'||in>'9')in=getchar();
while(in>='0'&&in<='9')r=(r<<1)+(r<<3)+(in^48),in=getchar();return r;
}
inline int MO(int x){return x<mo?x:x-mo;}
inline int poww(int x,int y)
{
int r(1);
while(y)
{
if(y&1)r=1ll*r*x%mo;
x=1ll*x*x%mo;
y>>=1;
}
return r;
}
struct num:public pair<double,double>
{
num(int x):pair<double,double>(x/base,x%base){}
num(double x,double y):pair<double,double>(x,y){}
int tnt(){return (int)round(first*base+second);}
friend num operator ~(const num &x){return num(x.first,-x.second);}
friend num operator /(const num &x,const double &y){return num(x.first/y,x.second/y);}
friend num operator +(const num &x,const num &y){return num(x.first+y.first,x.second+y.second);}
friend num operator -(const num &x,const num &y){return num(x.first-y.first,x.second-y.second);}
friend num operator *(const num &x,const num &y){return num(x.first*y.first-x.second*y.second,x.first*y.second+x.second*y.first);}
friend pair<num,num> gt(const num &a0,const num &a1,const num &b0,const num &b1)
{
num x0=(a0+a1)/2,x1=(a1-a0)/2*num(0,1),y0=(b0+b1)/2,y1=(b1-b0)/2*num(0,1);
return pair<num,num>(x0*y0+x1*y1*num(0,1),x0*y1+x1*y0*num(0,1));
}
friend num gt(const num &x,const num &y)
{
int nw=MO(1ll*MO((1ll*MO((long long)round(x.first)%mo+mo)*base%mo)+MO((long long)round(y.first+y.second)%mo+mo))*base%mo+MO((long long)round(x.second)%mo+mo));return num(nw/base,nw%base);
}
};
struct Poly:public vector<num>
{
int len;static vector<int>pos;
Poly(){}
Poly(const vector<num>&x){assign(x.begin(),x.end());len=x.size()-1;}
void dft(int len)
{
resize(len,num(0,0));for(int i=0;i<len;i++)if(pos[i]<i)std::swap(at(pos[i]),at(i));
for(int i=2;i<=len;i<<=1)
{
int leng=i>>1;
for(int j=0;j<len;j+=i)for(int k=0;k<leng;k++)
{
num nw=num(cos(Pie*k/leng),sin(Pie*k/leng))*at(j+k+leng);
at(j+k+leng)=at(j+k)-nw;at(j+k)=at(j+k)+nw;
}
}
}
void idft(int len)
{
for(int i=0;i<len;i++)if(pos[i]<i)std::swap(at(pos[i]),at(i));
for(int i=2;i<=len;i<<=1)
{
int leng=i>>1;
for(int j=0;j<len;j+=i)for(int k=0;k<leng;k++)
{
num nw=num(cos(Pie*k/leng),-sin(Pie*k/leng))*at(j+k+leng);
at(j+k+leng)=at(j+k)-nw;at(j+k)=at(j+k)+nw;
}
}
for(int i=0;i<len;i++)at(i)=at(i)/len;
}
friend Poly operator *(Poly x,Poly y)
{
int leng=x.len,len=leng+1;pos.assign(len,0);
for(int i=0;i<len;i++)pos[i]=(pos[i>>1]>>1)|(i&1?len>>1:0);x.dft(len),y.dft(len);
Poly p,q;p.assign(len,num(0,0));q.assign(len,num(0,0));
tie(p.front(),q.front())=gt(x.front(),~x.front(),y.front(),~y.front());
for(int i=1;i<len;i++)tie(p[i],q[i])=gt(x[i],~x[len-i],y[i],~y[len-i]);
x.assign(leng+1,num(0,0));y.clear();x.len=leng;p.idft(len);q.idft(len);
for(int i=0;i<=leng;i++)x[i]=gt(p[i],q[i]);return x;
}
friend Poly operator %(Poly x,int y)
{
if(y<x.len)x.len=y,x.resize(y+1,num(0,0));return x;
}
friend Poly gtnv(Poly z)
{
vector<int>seq;int le=z.len+1;while(le>1)seq.push_back(le-1),le=(le+1)>>1;reverse(seq.begin(),seq.end());Poly y(vector<num>(1,num(poww(z[0].tnt(),mo-2))));
for(vector<int>::iterator ite=seq.begin();ite!=seq.end();ite++)
{
Poly x=z%*ite;x=x*y%*ite;x.front()=num(MO(mo+2-x.front().tnt()));for(iterator ite=x.begin()+1;ite!=x.end();ite++)*ite=num(MO(mo-ite->tnt()));y=y*x%*ite;
}
return y;
}
};
vector<int>Poly::pos;
long long n;
int m;
int main()
{
n=readl();
m=read();
Poly f,g;
f.assign(m,num(0));
g.assign(m,num(0));
f.len=g.len=m-1;
f[0]=g[0]=num(1);
f[1%m]=f[1%m]+1;
while(n)
{
if(n&1)g=g*f;
f=f*f;
n>>=1;
}
printf("%d",g[0].tnt());
return 0;
}

最新文章

  1. mysql优化案例分析
  2. 与jquery serializeArray()一起使用的函数,主要来方便提交表单
  3. zoj.3865.Superbot(bfs + 多维dp)
  4. http://blog.csdn.net/rongyongfeikai2/article/details/41659353
  5. php初探
  6. LeetCode 55
  7. docker的网络-Container network interface(CNI)与Container network model(CNM)
  8. Myeclipse 激活代码 8.6以前的版本
  9. Docker存储驱动之ZFS简介
  10. java多线程编程核心技术——第五章总结
  11. hadoop基础教程免费分享
  12. OpenCV计算物体的重心坐标(2值图像)
  13. Function Composition vs Object Composition
  14. Python_匿名函数
  15. SDWebImage代码赏析
  16. Android 版本对于 API
  17. Anton and School - 2 CodeForces - 785D (组合计数,括号匹配)
  18. 一般web典型的项目目录结构
  19. 10-08常用的TIME和DATE函数以及各个函数对应的头文件
  20. 【BZOJ】1251: 序列终结者

热门文章

  1. SSH管理多密钥
  2. linux篇-Linux MBR分区、挂载操作步骤,逻辑卷扩容操作
  3. python操作MySQL与MySQL补充
  4. Dev C++编写C/C++程序 出现[Error] ld returned 1 exit status报错分析及解决
  5. OAuth2学习中的一些高频问题的QA
  6. 阻碍NB-IoT技术在智能水表发展的4个原因分析
  7. ForEach遍历集合、 集合容器
  8. Visual Studio Installer下载速度为0处理办法
  9. .NET中线程锁的使用
  10. 程序员必备,一款让你提高工作效率N倍的神器uTools