1. 程式人生 > >Codecraft-18 and Codeforces Round #458 C dp D 線段樹

Codecraft-18 and Codeforces Round #458 C dp D 線段樹

push bits 長度 define bsp mem har con tex

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 線段樹