【noip2017】
noip2017
小凯的疑惑
看到了一个简单易懂的证明
设\(x\),\(x\equiv ma(mod\ b)(0\le m<b)\)(因为\(m\ge b\)的话可以表示为\(ma=(m\%b)*a+\lfloor m/b\rfloor*b*a=(m\%b)a+(n+\lfloor m/b\rfloor)b\)而\(0\le m\%b< b\))
即\(x=ma+nb\) 显然\(n\ge0\)时一定能表示出来,所以\(n=-1\),\(0\le m<b-1\)
所以最大值为\((b-1)a-b=ab-a-b\)
时间复杂度
我lxy就是死,从这里跳下去,也不会做这道恶熏熏的题的!
逛公园
先dij跑一遍最短路 然后再类似dp来计算有多少条
若当前\(used[u][val]==1\)说明这个点还未走完又被进入了,构成了一个\(0\)环 无解
int tot=0,head[N];
struct edge{int v,w,nxt;}e[M];
void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
int dis[N];bool vis[N];
priority_queue<pii>q;
void clean(){memset(dis,inf,sizeof(dis)),memset(vis,0,sizeof(vis));}
void dij(int st){
clean();
q.push(make_pair(dis[st]=0,st));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u]) continue;vis[u]=1;
for(int i=head[u],v;i;i=e[i].nxt)
if((i&1)&&dis[v=e[i].v]>dis[u]+e[i].w) q.push(make_pair(-(dis[v]=dis[u]+e[i].w),v));
}
}
int f[N][55],used[N][55];
int dfs(int u,int val){
if(used[u][val]==1||fl) return fl=1;
if(used[u][val]==2) return f[u][val];
used[u][val]=1;
for(int i=head[u],v,w;i;i=e[i].nxt) if(!(i&1)){
w=dis[u]+val-dis[v=e[i].v]-e[i].w;
if(w>K||w<0) continue;
f[u][val]+=dfs(v,w),f[u][val]%=P;
}used[u][val]=2;
return f[u][val];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("T1.txt","r",stdin);
#endif
int T;rd(T);
while(T--){
memset(head,0,sizeof(head)),tot=ans=fl=0;
memset(used,0,sizeof(used)),memset(f,0,sizeof(f));
rd(n),rd(m),rd(K),rd(P);
for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
dij(1);f[1][0]=1;
for(int i=0;i<=K&&!fl;++i) ans+=dfs(n,i),ans%=P;
if(fl) puts("-1");
else printf("%d\n",ans);
}
return 0;
}
奶酪
dfs?搜一下有没有一个在最底层的洞能延伸到最顶层
long long x[maxn],y[maxn],z[maxn];
int vis[maxn];
long long su(long long int x1,long long x2,long long y1,long long y2,long long z1,long long z2){
long long wa=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2);
return wa;
}
void dfs(int x1,int y1,int z1,int cnt){
if(z1+r>=h) {fnd=1;return;}
vis[cnt]=1;
for(int i=1;i<=n;i++)
if(!vis[i]&&su(x1,x[i],y1,y[i],z1,z[i])<=4*r*r) dfs(x[i],y[i],z[i],i);
}
int main(){
scanf("%d",&t);
for(int i=1;i<=t;i++){
memset(vis,0,sizeof(vis));fnd=0;
scanf("%d%d%lld",&n,&h,&r);
for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
for(int i=1;i<=n;i++)
if(z[i]-r<=0) dfs(x[i],y[i],z[i],i);
if(fnd) printf("Yes\n");
else printf("No\n");
}
return 0;
}
宝藏
康代码把 枚举从哪个洞开始打
int cnt[N];
void dfs(int st){
for(int i=1;i<=n;++i)
if(st&(1<<(i-1))){
for(int j=1,nw,ret;j<=n;++j)
if(!(st&(1<<(j-1)))&&mp[i][j]!=inf)
if(nw=st|(1<<(j-1)),f[nw]>f[st]+mp[i][j]*cnt[i])
ret=cnt[j],f[nw]=f[st]+mp[i][j]*cnt[i],cnt[j]=cnt[i]+1,dfs(nw),cnt[j]=ret;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("T1.txt","r",stdin);
#endif
rd(n),rd(m);
memset(mp,inf,sizeof(mp));
for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),mp[u][v]=mp[v][u]=Min(mp[u][v],w);
for(int i=1;i<=n;++i){
memset(f,inf,sizeof(f)),f[1<<(i-1)]=0;
memset(cnt,inf,sizeof(cnt)),cnt[i]=1;
dfs(1<<(i-1)),ans=min(ans,f[(1<<n)-1]);
}
printf("%d",ans);
return 0;
}