码迷,mamicode.com
首页 > 其他好文 > 详细

Codecraft-18 and Codeforces Round #458 C dp D 线段树

时间:2018-01-25 12:04:48      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:none   sum   方案   put   ret   pair   force   main   number   

Codecraft-18 and Codeforces Round #458

C. Travelling Salesman and Special Numbers 

题意: 一个由0、1 组成的数 n,操作:n 有 m 个 1,就把 n 变为 m。 问 <=n 的数中有多少个恰好经过 k 次操作能变为 1。

tags:  dp[i][j] 表示长度为 i 且有 j 个 1  的串,比对应的 n 要小的方案数。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 1005, mod = 1e9+7;

ll  k, ans1[N], cnt, len;
char s[N];
ll  get(int x)  {
    ll  sum = 0;
    while(x) {
        if(x&1) ++sum;
        x >>= 1;
    }
    return sum;
}
ll  dp[N][N], C[N][N];
void Init()
{
    C[1][0] = C[1][1] = 1;
    rep(i,2,N-1)
    {
        C[i][0] = 1;
        rep(j,1,N-1)
            C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod;
    }

    if(s[len]==1) dp[len][1]=dp[len][0]=1;
    else dp[len][1]=0, dp[len][0]=1;
    per(i,len-1,1)
    {
        dp[i][0]=1;
        per(j,len-i+1,1)
        {
            if(s[i]==1)
                dp[i][j] = (dp[i+1][j-1]+C[len-i][j])%mod;
            else
                dp[i][j] = dp[i+1][j];
        }
    }
}
int main()
{
    scanf("%s%lld", s+1, &k);
    len = strlen(s+1);
    ll  tmp, cnt=0, ans=0;
    rep(i,1,len) if(s[i]==1) ++cnt;
    Init();
    rep(i,1,1000)
    {
        tmp = get(i);
        if(i==1) ans1[i] = 0;
        else  ans1[i] = ans1[tmp]+1;
        if(ans1[i]==k-1)
            ( ans += dp[1][i]%mod ) % mod;
    }
    if(k==0) ans = 1;
    if(k==1) ans = len-1;
    printf("%lld\n", (ans+mod)%mod);

    return 0;
}

 

D. Bash and a Tough Math Puzzle

题意: n 个数,两个操作:1、更改第 i 个数; 2、在区间 [l,r] 内,最多改变一个数,问是否能让 [l,r] 的gcd 等于 x 。

tags: 线段树单点更新,区间查询。如果区间内有超过 1 个数不是 x 的倍数,那就不能。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 500005;

int n, tree[N<<2], cnt;
void update(int ro, int L, int R, int x, int y)
{
    if(L==R && L==x) {
        tree[ro] = y;
        return ;
    }
    int mid = L+R>>1;
    if(x <= mid)
        update(ro<<1, L, mid, x, y);
    else
        update(ro<<1|1, mid+1, R, x, y);
    tree[ro] = __gcd(tree[ro<<1], tree[ro<<1|1]);
}
bool query(int ro, int L, int R, int l, int r, int x)
{
    if(cnt>1) return false;
    if(l<=L && R<=r)
    {
        if(tree[ro]%x==0) return true;
        if(L==R && tree[ro]%x!=0) { ++cnt; return false; }
    }
    int mid = L+R>>1;
    if(l<=mid) {
        query(ro<<1, L, mid, l, r, x);
    }
    if(mid<r) {
        query(ro<<1|1, mid+1, R, l, r, x);
    }
    if(cnt>1) return false;
    return true;
}
int main()
{
    scanf("%d", &n);
    int ai, ti, l, r, x, y, q;
    rep(i,1,n)
    {
        scanf("%d", &ai);
        update(1, 1, n, i, ai);
    }
    scanf("%d", &q);
    while(q--)
    {
        scanf("%d", &ti);
        if(ti==1) {
            scanf("%d%d%d", &l, &r, &x);
            cnt = 0;
            if(query(1, 1, n, l, r, x)) puts("YES");
            else puts("NO");
        }
        else {
            scanf("%d%d", &x, &y);
            update(1, 1, n, x, y);
        }
    }

    return 0;
}

Codecraft-18 and Codeforces Round #458 C dp D 线段树

标签:none   sum   方案   put   ret   pair   force   main   number   

原文地址:https://www.cnblogs.com/sbfhy/p/8336791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!