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;
}
View Code

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
", dis[2*k+1]);
    return 0;
}
View Code

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;
}
View Code

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;
}
View Code
原文地址:https://www.cnblogs.com/Y-Knightqin/p/13898061.html