Bayan 2015 Contest Warm Up(C 思维+模拟 D 思维+gcd)

题目链接

C. Kamal-ol-molk's Painting

题意:给你n*m的字符串矩阵,含有'X' 和'.'  现在你要求一个a*b矩形的刷子,每次只能向右走或者向下走,问能否将所有的'X’都刷一遍。

做法:暴力枚举a 和b的长度,然后暴力模拟即可,注意这里的时间复杂度应该是n方到n^3/2之间

代码参考:传送门

#include <bits/stdc++.h>
using namespace std;
const int N = 1000 + 10;
char g[N][N];
int n, m, minX, minY, ans;
int sum[N][N], cnt, tot;
int getSum(int a, int b, int x, int y) {
    return sum[a][b] - sum[a][y + 1] - sum[x + 1][b] + sum[x + 1][y + 1];
}
int ok(int a, int b) {
    int posX =minX,posY=minY;
    while(1) {
        if(posX+a-1>n||posY+b-1>m) return 0;
        if(getSum(posX,posY,posX+a-1,posY+b-1)!=a*b) return 0;
        if(getSum(posX,posY,n,m)==a*b&&getSum(posX,posY,posX+a-1,posY+b-1)==a*b) {
            return (cnt+a*b==tot);//终点,有可能在中间停止
        }
        bool flag1 = (a * b) == getSum(posX+1,posY,posX+a,posY+b-1);//向右走一格
        bool flag2 = (a * b) == getSum(posX,posY+1,posX+a-1,posY+b);//向下走一格
        if(!flag1&&!flag2) return 0;
        if(flag1&&flag2) return 0;
        if(flag1) ++posX,cnt+=b;//向右走一格,cnt总数等于列的个数
        else ++posY,cnt+=a;
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        scanf("%s", g[i] + 1);
    }
    minX = n + 1, minY = m + 1;
    ans = n * m + 1;
    for(int i=n;i>0;--i){
        for(int j=m;0<j;--j) {
            sum[i][j] = sum[i][j] - sum[i + 1][j + 1] + sum[i + 1][j] + sum[i][j + 1] + (g[i][j] == 'X');
            if(g[i][j] == 'X') {
                minX = min(i, minX), minY = min(j, minY);
                ++tot;
            }
        }
    }
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            if(ans <= i * j) continue;
            cnt = 0;
            if(ok(i, j)) ans = i * j;
        }
    }
    printf("%d\n", ans == n * m + 1 ? -1 : ans);

    return 0;
}

D. CGCDSSQ

题意:给你n长度的数组ai,接下来q次询问,输入x  问有多少个区间的gcd等于x

做法:dp[i][j]代表以i结尾的gcd为j的个数,由于gcd的特殊性质,j的个数不会超过log(a[i])个,所以map保存一下,暴力跑一遍就可以了。。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=(b);++i)
    #define mem(a,x) memset(a,x,sizeof(a))
    #define pb push_back
    #define pi pair<int, int>
    #define mk make_pair
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
    const int N=1e5+10;
    map<int,ll>mp1,mp2,ans;
    int n,a[N],q;
    int main()
    {
        cin>>n;
        rep(i,1,n) scanf("%d",&a[i]);
        for(int i=1;i<=n;++i){
            swap(mp1,mp2);
            mp2.clear();
            for(auto it:mp1){
                mp2[__gcd(it.first,a[i])]+=it.second;
            }
            mp2[a[i]]++;
            for(auto it:mp2){
                ans[it.first]+=it.second;
            }
        }
        int q;cin>>q;while(q--)
        {
            int x;
            scanf("%d",&x);
            printf("%lld\n",ans[x]);
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ccsu_deer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值