zoukankan      html  css  js  c++  java
  • #1076 : 与链

    描述

    给定 n 和 k。计算有多少长度为 k 的数组 a1, a2, ..., ak,(0≤ai) 满足:

    a1 + a2 + ... + ak = n

    对于任意的 i = 0, ..., k - 1 有 ai AND ai + 1 = ai + 1。其中AND是与操作。

    输入

    第一行包含一个整数 T - 测试数据组数(1 ≤ T ≤ 2)。接下来的 T 行,每行包含两个整数 k 和 n (k ≤ 105, n ≤ 104)。

    输出

    对于每组测试数据,输出一行表示对应的答案。答案可能很大,输出模 1000000009 后的结果。

    样例输入

    2
    3 2
    4 2

    样例输出

    2
    2


    注意到ai AND ai + 1 = ai + 1可以理解为是后面的数包含了前一个所有的二进制位。
    那么我们可以想象是将每个位分配给一个后缀,因为对于每一位,整个序列肯定是000011111111。
    设f[len][k]表示后len位,和为k,DP即可。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int mod=1000000009;
    ll f[20][100010];
    int main() {
        int T=read();
        while(T--) {
            int n=read(),k=read();
            memset(f,0,sizeof(f));
            rep(i,0,min(k,n)) f[0][i]=1; 
            rep(len,1,19) rep(i,0,k) {
                rep(j,0,n) if(i>=(1<<len)*j) (f[len][i]+=f[len-1][i-(1<<len)*j])%=mod;
                else break;
            }
            printf("%lld
    ",f[19][k]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    二叉树的序列化与反序列化
    寻找重复的子树
    [ABC216H] Random Robots
    Codeforces Round #741 (Div. 2)
    [Gym 102798K] Tree Tweaking
    CF798E Mike and code of a permutation
    CF1149E Election Promises
    [BZOJ 4311] 向量
    CF1268D Invertation in Tournament
    [做题笔记] 浅谈势能线段树在特殊区间问题上的应用
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4807630.html
Copyright © 2011-2022 走看看