2020ICPC·小米 网络选拔赛第一场 部分题解

Problem A

第一眼上去就直接筛,然后判断丢到map里面就好了,这个做法是会T掉的,考虑一下dp,dp的想法只需要在筛的时候判断一下就好了。因为这题在逻辑上是可以由上一个状态转移过来的,每个数的集合等于我这个数的个数和前面合法子集的最大值相加,所以我们只需要在筛的过程中做dp递推就好了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+10;
typedef long long ll;
void check_max (int &a,int b) { a=max (a,b);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
int vis[maxn],a[maxn];
int dp[maxn];

void solve () {
    int n;
    scanf ("%d",&n);
    for (int i=1,num;i<=n;i++) {
        scanf ("%d",&num);
        a[num]++;
        vis[num]=1;
    }
    int ans=0;
    for (int i=1;i<maxn;i++) {
        if (vis[i]==1) {
            dp[i]+=a[i];
            for (int j=i+i;j<maxn;j+=i) {
                if (vis[j]) check_max (dp[j],dp[i]);
            }
        }
        check_max (ans,dp[i]);
    }
    printf ("%d\n",ans);
}

int main () {
    int t;
    scanf ("%d",&t);
    while (t--) {
        solve ();
    }
    return 0;
}

Problem C

老水了。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<bitset>
#include<set>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#pragma GCC optimize(2)
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
const int maxn=2e5+10;
bool is_prime[maxn];


void solve () {
    string s;
    cin>>s;
    vector <int> v;
    int cnt=0;
    rev (i,0,s.size ()) {
        if (s[i]=='w') cnt++;
        if (cnt!=0&&s[i]!='w') {
            v.pb (cnt);
            cnt=0;
        }
        if (i==s.size ()-1&&cnt!=0) v.pb (cnt);
    }
    int ans=0;
    for (auto it:v) ans+= (2*it-1);
    cout<<ans<<endl;
    return ; 
}

int main () {
    ios::sync_with_stdio (false);
    solve ();
    return 0;
}

Problem I

常规bfs了,首先枚举四周墙壁的非法点,然后往内bfs做标记就好了。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<bitset>
#include<set>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#pragma GCC optimize(2)
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
const int maxn=1e3+10;
int n,m;
char maze[maxn][maxn];
int flag[maxn][maxn];
map <char,PII> mp;
int vis[maxn][maxn];
int moving[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool check (int x,int y) {
    if (vis[x][y]==0&&x>=1&&y<=m&&x<=n&&y>=1) return true;
    else return false;
}

void bfs (int x,int y) {
    queue <PII> q;
    q.push ({x,y});
    vis[x][y]=1;
    while (q.size ()) {
        PII now=q.front (); q.pop ();
        rep (i,0,3) {
            int dx=now.first+moving[i][0];
            int dy=now.second+moving[i][1];
            if (mp[maze[dx][dy]].first==(-moving[i][0])) {
                if (mp[maze[dx][dy]].second==(-moving[i][1])&&check (dx,dy)) {
                    vis[dx][dy]=1;
                    q.push ({dx,dy});
                } 
            }
        }
    }
    return ;
}

void solve () {
    cin>>n>>m;
    set <PII> s;
    rep (i,1,n) 
     rep (j,1,m) {
        cin>>maze[i][j];
        if (i==1&&maze[i][j]=='W') s.insert ({i,j});
        if (i==n&&maze[i][j]=='S') s.insert ({i,j});
        if (j==1&&maze[i][j]=='A') s.insert ({i,j});
        if (j==m&&maze[i][j]=='D') s.insert ({i,j});
     }
    for (auto it:s) bfs (it.first,it.second);
    rep (i,1,n) 
     rep (j,1,m) if (vis[i][j]) s.insert ({i,j});
    cout<<s.size ()<<endl;
    return ; 
}

int main () {
    mp['W']={-1,0},mp['A']={0,-1};
    mp['S']={1,0},mp['D']={0,1};
    ios::sync_with_stdio (false);
    solve ();
    return 0;
}

Problem J

就是我们能减就减,如果当前值不为0那么我们就构造以他为左上角的矩阵使矩阵的值全部减去当前值,如果遍历的过程中发现有负值那么就不能成功。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
typedef long long ll;
void check_max (int &a,int b) { a=max (a,b);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll s[maxn][maxn],dp[maxn][maxn];
int n,m,a,b;

void solve () {
    memset (dp,0,sizeof (dp));
    scanf ("%d%d%d%d",&n,&m,&a,&b);
    for (int i=1;i<=n;i++) 
     for (int j=1;j<=m;j++) scanf ("%lld",&s[i][j]);
    for (int i=1;i<=n;i++) 
     for (int j=1,x;j<=m;j++) {
        dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
        x=s[i][j]+dp[i][j];
        if (x==0) continue;
        else if (x<0) {
            puts ("QAQ");
            return ;
        }
        else if (x>0) {
            if (i+a-1>n||j+b-1>m) {
                puts ("QAQ");
                return ;
            }
            dp[i][j]-=x;
            dp[i][j+b]+=x;
            dp[i+a][j]+=x;
            dp[i+a][j+b]-=x;
        }
    }
    for (int i=1;i<=n;i++) 
     for (int j=1;j<=m;j++) if (s[i][j]+dp[i][j]) {
        puts ("QAQ");
        return ;
     }
    puts ("^_^");
    return ;
}

int main () {
    int t;
    scanf ("%d",&t);
    while (t--) {
        solve ();
    }
    return 0;
}
posted @ 2020-10-25 22:42  Luglucky  阅读(276)  评论(0编辑  收藏  举报