ICPC小米网络赛第一场
A Intelligent Warehouse
dp,筛出来所有的素数,然后再枚举所有的素数,由于约数个数定理,我们总能把与之成倍数关系的情况都累加起来。
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair #define ri register int #define pb push_back using namespace std; typedef long long ll; typedef double lf; typedef pair<ll, ll> pii; const int maxn = 1e7+1; const ll INF = 1e18; const int mod = 1e9+7; const double eps=1e-6; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int ip[maxn],i,n,p[maxn],cnt,dis[maxn],a[maxn],ans,x,dp[maxn],j; bool vis[maxn]; void get_prime() { memset(vis,0,sizeof(vis)); vis[1]=1; p[1]=1; ip[1]=1; cnt=1; for (int i=2;i<=maxn;i++) { if(!vis[i]) { cnt++; p[cnt]=i; ip[i]=cnt; } for (int j=1;j<=cnt && i*p[j]<=maxn;j++) { vis[i*p[j]]=1; } } } int main() { get_prime(); n=read(); for (i=1;i<=n;i++) { x=read(); a[x]++; } for (i=1;i<maxn;i++) { dp[i]+=a[i]; ans=max(ans,dp[i]); for (j=1;j<=cnt&& p[j]*i<maxn;j++) dp[p[j]*i]=max(dp[p[j]*i],dp[i]); } cout<<ans<<endl; return 0; }
B Intelligent Robot
计算几何
题目要求只能沿着墙走,换而言之,对我们有用的,只有点与点之间的直线路径对我们有用,所以只需判断两点之间是否不被墙挡,再计算距离,跑最短路即可。
判断两点之间是否不被墙挡=线段之间是否相交
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair #define ri register int #define pb push_back using namespace std; typedef long long ll; typedef double lf; typedef pair<ll, ll> pii; const int maxn =1e5+10; const int INF = 0x3f3f3f3f; const int mod = 1e9+7; const double eps=1e-6; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y*b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }p[maxn],s,t; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} struct node{ int to; lf dis; bool operator<(const node &b)const{ return dis>b.dis; } }; int n,m,k,i,j,flag,q; lf x,y; bool vis[maxn]; vector<node> G[maxn]; lf dis[maxn]; void dij(int s,int n){ //s是起点,dis是结果 fill(vis,vis+n+1,0); fill(dis,dis+n+1,INF); dis[s]=0; //last[s]=-1; static priority_queue<node> q; q.push({s,0}); while(!q.empty()){ int x=q.top().to; q.pop(); if(vis[x])continue; vis[x]=1; for(auto i:G[x]){ int p=i.to; if(dis[p]>dis[x]+i.dis){ dis[p]=dis[x]+i.dis; q.push({p,dis[p]}); } } } } bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd #define SJ(x) max(a.x,b.x)<min(c.x,d.x)\ || max(c.x,d.x)<min(a.x,b.x) if(SJ(x) || SJ(y))return 0; #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<0 return SJ2(a,b,c,d) && SJ2(c,d,a,b); } int main() { n=read(),m=read(),k=read(); for (i=1;i<=k;i++) { scanf("%lf%lf",&x,&y); p[i]=vec(x,y); scanf("%lf%lf",&x,&y); p[i+k]=vec(x,y); } scanf("%lf%lf",&x,&y); p[0]=vec(x,y); scanf("%lf%lf",&x,&y); p[2*k+1]=vec(x,y); for (i=0;i<=2*k+1;i++) { for (j=i+1;j<=2*k+1;j++) { flag=1; for (q=1;q<=k;q++) if (judge(p[i],p[j],p[q],p[q+k])) { flag=0; break; } if (flag) { G[i].pb({j,(p[i]-p[j]).len()}); G[j].pb({i,(p[i]-p[j]).len()}); } } } dij(0,2*k+1); printf("%.4f\n", dis[2*k+1]); return 0; }
C Smart Browser
水题
D Router Mesh
在求割点的模板中,如果low[v]>=low[u],cut[u]=true则说明u是割点,那么改成cut[u]++,说明去掉u点会多形成cut[u]个连通图
假设u是根节点
1.cut[u]=0 说明u为孤立点 则去掉后连通数少1
2.cut[u]=1 说明u只有一个儿子 则去掉后连通数不变
3.cut[u]>=2 说明u有>=2个儿子 则去掉后连通数多cut[u]-1
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair #define ri register int #define pb push_back using namespace std; typedef long long ll; typedef double lf; typedef pair<ll, ll> pii; const int maxn = 1e6+10; const ll INF = 1e18; const int mod = 1e9+7; const double eps=1e-6; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} vector<int>G[maxn]; int dfn[maxn],low[maxn],cut[maxn],i,u,v; int n,m,ans,tot; void tarjan(int u,int fa) { dfn[u]=low[u]=++tot; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(v==fa)continue; if(!dfn[v]) { tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u])cut[u]++; } low[u]=min(low[u],dfn[v]); } } int main() { n=read(),m=read(); for (i=1;i<=m;i++) { u=read(),v=read(); G[u].pb(v); G[v].pb(u); } for (i=1;i<=n;i++) { if (!dfn[i]) { ans++; tarjan(i,-1); cut[i]--; } } for (i=1;i<=n;i++) cout<<cut[i]+ans<<" "; cout<<endl; return 0; }
I Walking Machine
水题
J Matrix Subtraction
把原矩阵换成差分矩阵,那么与一个子矩阵相减,我们只需改变差分矩阵的四个点,时间效率大大提高,同时我们要考虑到底减多少。对于左上角的点,我们只能在这一次矩阵相减把这个点减至0,因为后续我们不可能回头再进行矩阵相减把左上角的点变成0,所以我们只需每次通过差分矩阵来反求出原矩阵的左上角的元素值,减去这个值把左上角元素变为0,再后面判断是否元素出现<0的情况即可。
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair #define ri register int #define pb push_back using namespace std; typedef long long ll; typedef double lf; typedef pair<ll, ll> pii; const int maxn = 1e3+10; const ll INF = 1e18; const int mod = 1e9+7; const double eps=1e-6; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int n,m,a,b,t,i,j,flag; ll d[maxn][maxn],G[maxn][maxn]; void add(int xa,int ya,int xb,int yb,ll val) { d[xa][ya]+=val; d[xb][yb]+=val; d[xa][yb]-=val; d[xb][ya]-=val; } int main() { t=read(); while (t--) { n=read(),m=read(),a=read(),b=read(); memset(d,0,sizeof(d)); for (i=1;i<=n;i++) for (j=1;j<=m;j++) G[i][j]=read(); for (i=1;i<=n;i++) for (j=1;j<=m;j++) d[i][j]=G[i][j]-G[i-1][j]-G[i][j-1]+G[i-1][j-1]; flag=0; for (i=1;i<=n&&!flag;i++) for (j=1;j<=m&&!flag;j++) { d[i][j]=d[i][j]+d[i-1][j]+d[i][j-1]-d[i-1][j-1]; if (d[i][j]<0) flag=1; else if (d[i][j]>0) { if (i+a-1>n || j+b-1>m) flag=1; else add(i,j,i+a,j+b,-d[i][j]); } } if (flag) cout<<"QAQ"<<endl; else cout<<"^_^"<<endl; } return 0; }