【1th】 小米邀请赛

传送门

A.Intelligent Warehous

题意

给定\(n\)个数,从这\(n\)个数中选出一些数来,这些数构成的集合中任选两个数其中的一个都能被另一个整除
求最大的集合中数字的个数

数据范围

\(1\leq n\leq 2\times 10^{5}\)

题解

数论动态规划,倍数法,\(dp[i]\)表示数字\(i\)之前所有数字所在集合的最大数量

  • 不能通过倍数进行累加,如果是累加的话\(3、4\)两个数不存在其中一个是另一个的约数,同样会加到\(12\)
  • 只需要将当前数的倍数更新为最大值即可,后面再加上当前数的个数

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
const int N=1e7+10; 
int n;
bool st[N];
int dp[N],cnt[N];
int main(){
    scanf("%d",&n);
    rep(i,1,n+1){
        int x;scanf("%d",&x);
        cnt[x]++;
        st[x]=1;
    }
    int ans=0;
    rep(i,1,N){
        if(!st[i]) continue;
        dp[i]+=cnt[i];
        ans=max(ans,dp[i]);
        for(int j=i+i;j<N;j+=i)
            if(dp[i] >= dp[j])
                dp[j]=dp[i];
    }
    cout<<ans<<endl;
}

C. Smart Browser

题意

统计一个字符串中\(w\)中的$/$字符的数量

数据范围

\(1\leq |s| \leq 10^{5}\)

题解

只有\(w\)才会产生,一段连续长度为\(len\)\(w\)字符串中的数量为\(2\times len -1\),只需要累计连续的长度计算即可,计算的时候需要判断是否为\(0\),否则\(-1\)后影响答案

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)

int main(){
    string s;
    cin>>s;
    int len=s.size();
    int leng=0;
    int ans=0;
    rep(i,0,len){
        if(s[i]=='w') ++leng;
        else{
            if(leng){   
                ans+=2*leng-1;
                leng=0;            
            }
        }
    }
    if(leng) ans+=2*leng-1;
    cout<<ans<<endl;
}

I. Walking Machine

题意

给定一个大小为\(n\times m\)的迷宫,每个格点上有一个字符表示这个格子可以移动的方向

  • \(W\):向左移动,\((x,y)\rightarrow (x-1,y)\)
  • \(A\):向上移动,\((x,y)\rightarrow (x,y-1)\)
  • \(S\):向右移动,\((x,y)\rightarrow (x+1,y)\)
  • \(D\):向下移动,\((x,y)\rightarrow (x,y+1)\)

求出在所有格点出发能够走出迷宫的格点数量

数据范围

\(1\leq n,m\leq 1000\)

题解

对于每条边,建立反向边,一个源点\(0\)表示当前图的界外,如果边出界全部连到点\(0\)处,
然后从表示界外的源点\(0\)开始\(dfs\)遍历图即可,每个点只需要被遍历一次,累计点数即可

  • 二维图的格点\((x,y)\)压缩成一维后值为\(x\times m + y\)\(n\)表示行数,\(m\)表示列数

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
const int N=1010,M=N*N;
int n,m;
char s[N][N];
bool st[M];
struct node {
    int to,ne;
}e[M];
int h[M],id;
int ans=0;
int get(int x,int y){
    if(x<1 || x>n || y<1 || y>m) return 0;
    return (x-1)*m+y;
}
void add(int u,int v){
    e[++id].to=v;
    e[id].ne=h[u];
    h[u]=id;
}
void dfs(int u){
    for(int i=h[u];i;i=e[i].ne){
        int to=e[i].to;
        if(st[to]) continue;
        st[to]=1;ans++;
        dfs(to);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    rep(i,1,n+1) scanf("%s",s[i]+1);

    rep(i,1,n+1) rep(j,1,m+1){
        if(s[i][j]=='W') add(get(i-1,j),get(i,j));
        else if(s[i][j]=='A') add(get(i,j-1),get(i,j));
        else if(s[i][j]=='S') add(get(i+1,j),get(i,j));
        else if(s[i][j]=='D') add(get(i,j+1),get(i,j));
    }

    st[0]=1;
    dfs(0);
    cout<<ans<<endl;
}      

J. Matrix Subtraction

题意

给定一个\(n\times m\)大小的矩阵,给定一个\(a\times b\)的子矩阵范围,每次可以将大小为\(a\times b\)的任意子矩阵中所有元素值\(-1\)问当前的\(n\times m\)的矩阵能否经过操作变为全\(0\)的矩阵

数据范围

\(1\leq n,m\leq 1000\)

题解

对于格点\(M_{1,1}\),只能被\((1,1)\sim (a,b)\)的子矩阵处理,所以\((1,1)\sim (a,b)\)的选择次数是确定的,同理可以求出\((1,2)\sim (a,b+1)\)及其它所有子矩阵被选择的次数
\(C_{i,j}\)\((i,j)\sim (i+a-1,j+b-1)\)被选择的次数,可以得到:

\[C_{i,j}=M_{i,j}-\sum_{u=0,v=0}^{a-1}\sum_{u=0,v=0}^{b-1}(u \neq 0 \; or\; v\neq 0)C_{i-u,j-v} \]

运用前缀和+二维差分可以\(O(1)\)计算出

  • 只需要判断每个\(C_{i,j}\)是否\(\geq 0\)以及所有\(M_{i,j}\)能否恰好变为\(0\)

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)

const int N=1010;

int n,m,a,b;
int g[N][N];
int c[N][N];
void solve(){
    scanf("%d%d%d%d",&n,&m,&a,&b);
    rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&g[i][j]);

    rep(i,1,n+1) rep(j,1,m+1) c[i][j]=0;

    rep(i,1,n+1) rep(j,1,m+1){
        c[i][j]=c[i][j]+c[i-1][j]+c[i][j-1]-c[i-1][j-1];
        g[i][j]-=c[i][j];

        if(g[i][j]<0) {
            return puts("QAQ"),void(0);
        }
        if (i+a-1>n||j+b-1>m){
            if (g[i][j]) return puts("QAQ"),void(0);
        }
        else{
            c[i][j]+=g[i][j];
            c[i+a][j]-=g[i][j];
            c[i][j+b]-=g[i][j];
            c[i+a][j+b]+=g[i][j];
        }
    }
    puts("^_^");
}
int main(){
    int _;scanf("%d",&_);
    while(_--) solve();
}
posted @ 2020-10-26 15:19  Hyx'  阅读(163)  评论(0编辑  收藏  举报