1. 程式人生 > >ccpc 2016 changchun 長春(4.12訓練)

ccpc 2016 changchun 長春(4.12訓練)

前綴 取出 != rand() pid 匹配 並且 貢獻 如果

概述

訓練來源: ccpc2016 長春賽區區域賽

訓練時間: 2019-04-02 13:00 至 2019-04-02 18:00

訓練人: jmx,cy

通過題目: 7/12:B,D,F,G,H,I,J

排名: 11/181

金牌題數: 7

出線題數: 9

賽後補題: E,K


題解(按照題目通過順序)

B - Fraction (cy)

題目來源: HDU - 5912

00:07:54 通過 (1次提交)

簽到題,cy碼的比較穩

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
#include <complex>
#include <queue>
#include <algorithm>
#include <string>
#include <stack>
#include <bitset>
#include <cmath>
#include <set>

int N = 1e6, SZ = 320, INF = 1 << 29;
long long LINF = (1LL << 61), mod = 1e9 + 7;
const long double eps = 1e-9, PI = acos(-1.0);

#define lowbit(x) (x & (-(x)))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define rp(a, b, c) for (int a = b; a <= c; ++a)
#define RP(a, b, c) for (int a = b; a < c; ++a)
#define lp(a, b, c) for (int a = b; a >= c; --a)
#define LP(a, b, c) for (int a = b; a > c; --a)
#define rps(i, s) for (int i = 0; s[i]; i++)
#define fson(u) for (int i = g[u]; ~i; i = edg[i].nxt)
#define adde(u, v) edg[++ecnt] = Edge(u, v, 0, g[u]), g[u] = ecnt
#define addew(u, v, w) edg[++ecnt] = Edge(u, v, w, g[u]), g[u] = ecnt
#define MID (l + r >> 1)
#define mst(a, v) memset(a, v, sizeof(a))
#define bg(x)                Edge edg[maxn << x];     int g[maxn], ecnt
#define ex(v)      cout << v;     return 0
#define debug(x) cout << "debug: " << x << endl;
#define sqr(x) ((x) * (x))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef complex<double> cpx;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

char READ_DATA;
int SIGNAL_INPUT;
template <typename Type>
inline Type ru(Type &v)
{
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
        v = v * 10 + READ_DATA - '0';
    v *= SIGNAL_INPUT;
    return v;
}
inline ll modru(ll &v)
{
    ll p = 0;
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    p = v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
    {
        v = (v * 10 + READ_DATA - '0') % mod;
        p = (p * 10 + READ_DATA - '0') % (mod - 1);
    }
    v *= SIGNAL_INPUT;
    return p;
}
template <typename A, typename B>
inline int ru(A &x, B &y)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    return 2;
}
template <typename A, typename B, typename C>
inline int ru(A &x, B &y, C &z)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    return 3;
}
template <typename A, typename B, typename C, typename D>
inline int ru(A &x, B &y, C &z, D &w)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    ru(w);
    return 4;
}
inline ll gcd(ll a, ll b)
{
    while (b)
    {
        a %= b;
        swap(a, b);
    }
    return a;
}

inline ll fastmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return (a * b - (ll)((long double)a * b / mod) * mod + mod) % mod;
}

inline ll dirmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return a * b % mod;
}

inline ll ss(ll a, ll b, ll mod = 1e9 + 7, ll(*mul)(ll, ll, ll) = dirmul)
{
    if (b < 0)
    {
        b = -b;
        a = ss(a, mod - 2, mod);
    }
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans = mul(ans, a, mod);
        a = mul(a, a, mod);
        b >>= 1;
    }
    return ans;
}
inline int isprime(ll n)
{
    if (n == 1)
        return 0;

    for (ll d = 2; d * d <= n; ++d)
    {
        if (n % d == 0)
            return 0;
    }

    return 1;
}

template <typename Type>
void brc(Type *a, int n)
{
    int k;
    for (int i = 1, j = n / 2; i < n - 1; i++)
    {
        if (i < j)
            swap(a[i], a[j]);

        k = n >> 1;
        while (j >= k)
        {
            j ^= k;
            k >>= 1;
        }
        if (j < k)
            j ^= k;
    }
}
void fft(cpx *a, int n, int inv = 1)
{
    cpx u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        cpx wn(cos(inv * 2.0 * PI / h), sin(inv * 2.0 * PI / h));
        for (int j = 0; j < n; j += h)
        {
            cpx w(1, 0);
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)];
                a[k] = u + t;
                a[k + (h >> 1)] = u - t;
                w *= wn;
            }
        }
    }
    if (inv == -1)
        RP(i, 0, n)
        a[i] /= n;
}
void ntt(ll *a, int n, int inv = 1)
{
    ll u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        ll wn = ss(3, (mod - 1) / h);
        if (inv == -1)
            wn = ss(wn, mod - 2);
        for (int j = 0; j < n; j += h)
        {
            ll w = 1;
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)] % mod;
                a[k] = (u + t) % mod;
                a[k + (h >> 1)] = (u - t + mod) % mod;
                (w *= wn) %= mod;
            }
        }
    }
    if (inv == -1)
    {
        ll tmp = ss(n, mod - 2);
        RP(i, 0, n)
            (a[i] *= tmp) %= mod;
    }
}
struct Edge
{
    int u, v, nxt;
    //ll w;
    Edge(int _u = 0, int _v = 0, /*ll _w = 0,*/ int _nxt = 0)
    {
        u = _u;
        v = _v;
        //w = _w;
        nxt = _nxt;
    }

    /*int operator<(const Edge &b) const
    {
        return w < b.w;
    }*/
};
struct CMP
{
    int operator()(const int &a, const int &b) const
    {
        return a > b;
    }
};

const int maxn = 1e2+ 5;
/*------------------------------------------------------------------------yah01------------------------------------------------------------------------*/

int n, a[maxn], b[maxn];

pll f(int i)
{
    if (i == n)
    {
        ll d = gcd(a[n], b[n]);
        return pll(b[n] / d, a[n] / d);
    }

    pll t = f(i + 1);
    ll x = b[i] * t.second, y = a[i] * t.second + t.first;
    ll d = gcd(x, y);
    return pll(x / d, y / d);
}

int main()
{   
    int T;
    ru(T);
    rp(t,1,T)
    {
        ru(n);
        rp(i, 1, n) ru(a[i]);
        rp(i, 1, n) ru(b[i]);

        pll ans = f(1);
        printf("Case #%d: %lld %lld\n", t,ans.first, ans.second);
    }
    return 0;
}

/*
5
2 4 6 8 10
-1 2 2 2
1000
+ 1 10
+ 1 -2
+ 1 1
*/

D - Triangle (jmx)

題目來源: HDU-5914

00:19:22 通過(一次提交)

暴力枚舉即可。簽到題。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x6fffffff
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int mx=(1<<20);
int f[30],a[30];
int main()
{
    for(int op=0;op<mx;op++)
    {
        int cnt=0;
        for(int i=0;i<20;i++)
            if(((1<<i)&op)>0)a[++cnt]=i+1;
        if(cnt<=2)
        {
            for(int i=a[cnt];i<=20;i++)f[i]=max(cnt,f[i]);
        }
        else{
            bool flag=0;
            for(int i=1;i<=cnt-2;i++)
            {
                if(a[i]+a[i+1]>a[i+2]){flag=1;break;}
            }
            if(!flag)
                for(int i=a[cnt];i<=20;i++)f[i]=max(cnt,f[i]);
        }
    }
    for(int i=1;i<=20;i++)f[i]=i-f[i];
    int T=read();
    for(int cas=1;cas<=T;cas++)
    {
        int n=read();
        printf("Case #%d: %d\n",cas,f[n]);
    }
    return 0;
}

F - Harmonic Value Description (jmx)

題目來源:HDU-5916

00:31:04 通過(1次提交)

通過觀察可以得出:

  1. $P_i,P_{i-1}$一個是奇數一個是偶數時,$gcd(P_i,P_{i-1})=1$
  2. $P_i,P_{i-1}$為連續的奇數時,$gcd(P_i,P_{i-1})=1$
  3. $P_i,P_{i-1}$為連續的偶數時,$gcd(P_i,P_{i-1})=2$

那麽一定可以通過如下方法構造出所求和為$n-1+i$的序列:將前$i$個偶數按順序放在最前面,然後將前$i$個奇數按順序放在這些偶數的後面,再將剩下的所有數按順序放在最後。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x6fffffff
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int mx=(1<<20);
int f[30],a[30];
int main()
{
    for(int op=0;op<mx;op++)
    {
        int cnt=0;
        for(int i=0;i<20;i++)
            if(((1<<i)&op)>0)a[++cnt]=i+1;
        if(cnt<=2)
        {
            for(int i=a[cnt];i<=20;i++)f[i]=max(cnt,f[i]);
        }
        else{
            bool flag=0;
            for(int i=1;i<=cnt-2;i++)
            {
                if(a[i]+a[i+1]>a[i+2]){flag=1;break;}
            }
            if(!flag)
                for(int i=a[cnt];i<=20;i++)f[i]=max(cnt,f[i]);
        }
    }
    for(int i=1;i<=20;i++)f[i]=i-f[i];
    int T=read();
    for(int cas=1;cas<=T;cas++)
    {
        int n=read();
        printf("Case #%d: %d\n",cas,f[n]);
    }
    return 0;
}

H - Sequence I (cy)

題目來源:HDU-5918

01:03:06 通過(1次提交)

根據題意暴力枚舉匹配,使用kmp算法加速即可

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
#include <complex>
#include <queue>
#include <algorithm>
#include <string>
#include <stack>
#include <bitset>
#include <cmath>
#include <set>

int N = 1e6, SZ = 320, INF = 1 << 29;
long long LINF = (1LL << 61), mod = 1e9 + 7;
const long double eps = 1e-9, PI = acos(-1.0);

#define lowbit(x) (x & (-(x)))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define rp(a, b, c) for (int a = b; a <= c; ++a)
#define RP(a, b, c) for (int a = b; a < c; ++a)
#define lp(a, b, c) for (int a = b; a >= c; --a)
#define LP(a, b, c) for (int a = b; a > c; --a)
#define rps(i, s) for (int i = 0; s[i]; i++)
#define fson(u) for (int i = g[u]; ~i; i = edg[i].nxt)
#define adde(u, v) edg[++ecnt] = Edge(u, v, 0, g[u]), g[u] = ecnt
#define addew(u, v, w) edg[++ecnt] = Edge(u, v, w, g[u]), g[u] = ecnt
#define MID (l + r >> 1)
#define mst(a, v) memset(a, v, sizeof(a))
#define bg(x)                Edge edg[maxn << x];     int g[maxn], ecnt
#define ex(v)      cout << v;     return 0
#define debug(x) cout << "debug: " << x << endl;
#define sqr(x) ((x) * (x))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef complex<double> cpx;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

char READ_DATA;
int SIGNAL_INPUT;
template <typename Type>
inline Type ru(Type &v)
{
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
        v = v * 10 + READ_DATA - '0';
    v *= SIGNAL_INPUT;
    return v;
}
inline ll modru(ll &v)
{
    ll p = 0;
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    p = v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
    {
        v = (v * 10 + READ_DATA - '0') % mod;
        p = (p * 10 + READ_DATA - '0') % (mod - 1);
    }
    v *= SIGNAL_INPUT;
    return p;
}
template <typename A, typename B>
inline int ru(A &x, B &y)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    return 2;
}
template <typename A, typename B, typename C>
inline int ru(A &x, B &y, C &z)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    return 3;
}
template <typename A, typename B, typename C, typename D>
inline int ru(A &x, B &y, C &z, D &w)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    ru(w);
    return 4;
}
inline ll gcd(ll a, ll b)
{
    while (b)
    {
        a %= b;
        swap(a, b);
    }
    return a;
}

inline ll fastmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return (a * b - (ll)((long double)a * b / mod) * mod + mod) % mod;
}

inline ll dirmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return a * b % mod;
}

inline ll ss(ll a, ll b, ll mod = 1e9 + 7, ll(*mul)(ll, ll, ll) = dirmul)
{
    if (b < 0)
    {
        b = -b;
        a = ss(a, mod - 2, mod);
    }
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans = mul(ans, a, mod);
        a = mul(a, a, mod);
        b >>= 1;
    }
    return ans;
}
inline int isprime(ll n)
{
    if (n == 1)
        return 0;

    for (ll d = 2; d * d <= n; ++d)
    {
        if (n % d == 0)
            return 0;
    }

    return 1;
}

template <typename Type>
void brc(Type *a, int n)
{
    int k;
    for (int i = 1, j = n / 2; i < n - 1; i++)
    {
        if (i < j)
            swap(a[i], a[j]);

        k = n >> 1;
        while (j >= k)
        {
            j ^= k;
            k >>= 1;
        }
        if (j < k)
            j ^= k;
    }
}
void fft(cpx *a, int n, int inv = 1)
{
    cpx u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        cpx wn(cos(inv * 2.0 * PI / h), sin(inv * 2.0 * PI / h));
        for (int j = 0; j < n; j += h)
        {
            cpx w(1, 0);
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)];
                a[k] = u + t;
                a[k + (h >> 1)] = u - t;
                w *= wn;
            }
        }
    }
    if (inv == -1)
        RP(i, 0, n)
        a[i] /= n;
}
void ntt(ll *a, int n, int inv = 1)
{
    ll u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        ll wn = ss(3, (mod - 1) / h);
        if (inv == -1)
            wn = ss(wn, mod - 2);
        for (int j = 0; j < n; j += h)
        {
            ll w = 1;
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)] % mod;
                a[k] = (u + t) % mod;
                a[k + (h >> 1)] = (u - t + mod) % mod;
                (w *= wn) %= mod;
            }
        }
    }
    if (inv == -1)
    {
        ll tmp = ss(n, mod - 2);
        RP(i, 0, n)
            (a[i] *= tmp) %= mod;
    }
}
struct Edge
{
    int u, v, nxt;
    //ll w;
    Edge(int _u = 0, int _v = 0, /*ll _w = 0,*/ int _nxt = 0)
    {
        u = _u;
        v = _v;
        //w = _w;
        nxt = _nxt;
    }

    /*int operator<(const Edge &b) const
    {
        return w < b.w;
    }*/
};
struct CMP
{
    int operator()(const int &a, const int &b) const
    {
        return a > b;
    }
};

const int maxn = 1e6+ 5;
/*------------------------------------------------------------------------yah01------------------------------------------------------------------------*/

int n, m, p;
int a[maxn], b[maxn];
int f[maxn];

void KMP()
{
    int j;
    f[0] = f[1] = 0;
    RP(i, 1, m)
    {
        j = f[i];
        while (j && b[i] != b[j]) j = f[j];
        f[i + 1] = b[i] == b[j] ? j + 1 : 0;
    }
}

int main()
{   
    int T;
    ru(T);
    rp(t,1,T)
    {
        ru(n, m, p);
        RP(i, 0, n) ru(a[i]);
        RP(i, 0, m) ru(b[i]);
        KMP();

        int j, ans = 0;
        RP(s, 0, p)
        {
            j = 0;
            for (int i = s; i < n; i += p)
            {
                while (j && a[i] != b[j]) j = f[j];
                if (a[i] == b[j]) ++j;
                if (j == m)
                {
                    ++ans;
                    j = f[j];
                }
            }
        }

        printf("Case #%d: %d\n", t, ans);
    }
    return 0;
}

/*
5
2 4 6 8 10
-1 2 2 2
1000
+ 1 10
+ 1 -2
+ 1 1
*/

I - Sequence II (jmx)

題目來源:HDU-5919

02:03:53 通過(2次提交)

統計$[l,r]$之間只出現一次的數的個數,我們利用主席樹記錄相同的數的前一個位置是多少,很容易得到區間有多少個不同的數。然後可以通過二分來解決,但是$O(nlogn)$的時間復雜度怕超時就沒寫。

考慮一下可以倒著插入,某個數出現的位置$x$,上一次出現的位置為$y$,則在$root_x$處的$x$位置+1,在$root_y$處的$x$位置-1。求一個後綴和,$root_l$中記錄的就是從所有以$l$為左端點的區間中有多少個位置的數是第一次出現的。對於每次詢問,我們只要在$root_l$的線段樹上先求出$[l,r]$有多少個數(假設為t),並在$root_l$的線段樹上二分出第$\lfloor (t+1)/2\rfloor$個數的位置就行了。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x6fffffff
#define N 200086
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
map<int,int>mp;
int a[N],pre[N],nxt[N],root[N];
int n,m;
int cnt;
struct node{int l,r,w;}f[N*80];
void ins(int &i,int l,int r,int ps,int dd)
{
    f[++cnt]=f[i];i=cnt;f[cnt].w+=dd;
    if(l==r)return;
    int mid=(l+r)/2;
    if(ps<=mid)ins(f[i].l,l,mid,ps,dd);else ins(f[i].r,mid+1,r,ps,dd);
}
int ask(int i,int l,int r,int lt,int rt)
{
    if(lt<=l&&r<=rt)return f[i].w;
    int mid=(l+r)/2,res=0;
    if(lt<=mid)res+=ask(f[i].l,l,mid,lt,rt);
    if(mid+1<=rt)res+=ask(f[i].r,mid+1,r,lt,rt);
    return res;
}
int find(int i,int l,int r,int rk)
{
    if(l==r)return l;
    int mid=(l+r)/2,tmp=f[f[i].l].w;
    if(tmp>=rk)return find(f[i].l,l,mid,rk);
        else return find(f[i].r,mid+1,r,rk-tmp);
    
}
int main()
{
    int T=read();
    for(int cas=1;cas<=T;cas++)
    {
        int n=read(),m=read();
        printf("Case #%d:",cas);
        cnt=0;mp.clear();
        for(int i=1;i<=n+1;i++)root[i]=pre[i]=nxt[i]=0;
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
            pre[i]=mp[a[i]];mp[a[i]]=i;
            if(pre[i]!=0)nxt[pre[i]]=i;
        }
        for(int i=n;i;i--)
        {
            root[i]=root[i+1];
            ins(root[i],1,n,i,1);
            if(nxt[i]!=0)ins(root[i],1,n,nxt[i],-1);
        }
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            int l=(read()+ans)%n+1,r=(read()+ans)%n+1;
            if(l>r)swap(l,r);
            int k=ask(root[l],1,n,l,r);
            int rk=(k+1)/2;
            ans=find(root[l],1,n,rk);
            printf(" %d",ans);
        }
        puts("");
    }
    return 0;
}

J - Ugly Problem (cy)

題目來源:HDU-5920

02:49:50 通過(5次提交)

將數字的前一半提取出來,然後將這個數字減$1$,然後把這個數字做對稱形成後一半。用原來的數減去這個小於原數的回文數,得到一個新的數。之後對新的數執行以上操作,直到變成一位數。這樣可以保證每次都可以把數字的長度減小一半。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
#include <complex>
#include <queue>
#include <algorithm>
#include <string>
#include <stack>
#include <bitset>
#include <cmath>
#include <set>

int N = 1e6, SZ = 320, INF = 1 << 29;
long long LINF = (1LL << 61), mod = 1e9 + 7;
const long double eps = 1e-9, PI = acos(-1.0);

#define lowbit(x) (x & (-(x)))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define rp(a, b, c) for (int a = b; a <= c; ++a)
#define RP(a, b, c) for (int a = b; a < c; ++a)
#define lp(a, b, c) for (int a = b; a >= c; --a)
#define LP(a, b, c) for (int a = b; a > c; --a)
#define rps(i, s) for (int i = 0; s[i]; i++)
#define fson(u) for (int i = g[u]; ~i; i = edg[i].nxt)
#define adde(u, v) edg[++ecnt] = Edge(u, v, 0, g[u]), g[u] = ecnt
#define addew(u, v, w) edg[++ecnt] = Edge(u, v, w, g[u]), g[u] = ecnt
#define MID (l + r >> 1)
#define mst(a, v) memset(a, v, sizeof(a))
#define bg(x)                Edge edg[maxn << x];     int g[maxn], ecnt
#define ex(v)      cout << v;     return 0
#define debug(x) cout << "debug: " << x << endl;
#define sqr(x) ((x) * (x))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef complex<double> cpx;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

char READ_DATA;
int SIGNAL_INPUT;
template <typename Type>
inline Type ru(Type &v)
{
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
        v = v * 10 + READ_DATA - '0';
    v *= SIGNAL_INPUT;
    return v;
}
inline ll modru(ll &v)
{
    ll p = 0;
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    p = v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
    {
        v = (v * 10 + READ_DATA - '0') % mod;
        p = (p * 10 + READ_DATA - '0') % (mod - 1);
    }
    v *= SIGNAL_INPUT;
    return p;
}
template <typename A, typename B>
inline int ru(A &x, B &y)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    return 2;
}
template <typename A, typename B, typename C>
inline int ru(A &x, B &y, C &z)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    return 3;
}
template <typename A, typename B, typename C, typename D>
inline int ru(A &x, B &y, C &z, D &w)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    ru(w);
    return 4;
}
inline ll gcd(ll a, ll b)
{
    while (b)
    {
        a %= b;
        swap(a, b);
    }
    return a;
}

inline ll fastmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return (a * b - (ll)((long double)a * b / mod) * mod + mod) % mod;
}

inline ll dirmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return a * b % mod;
}

inline ll ss(ll a, ll b, ll mod = 1e9 + 7, ll(*mul)(ll, ll, ll) = dirmul)
{
    if (b < 0)
    {
        b = -b;
        a = ss(a, mod - 2, mod);
    }
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans = mul(ans, a, mod);
        a = mul(a, a, mod);
        b >>= 1;
    }
    return ans;
}
inline int isprime(ll n)
{
    if (n == 1)
        return 0;

    for (ll d = 2; d * d <= n; ++d)
    {
        if (n % d == 0)
            return 0;
    }

    return 1;
}

template <typename Type>
void brc(Type *a, int n)
{
    int k;
    for (int i = 1, j = n / 2; i < n - 1; i++)
    {
        if (i < j)
            swap(a[i], a[j]);

        k = n >> 1;
        while (j >= k)
        {
            j ^= k;
            k >>= 1;
        }
        if (j < k)
            j ^= k;
    }
}
void fft(cpx *a, int n, int inv = 1)
{
    cpx u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        cpx wn(cos(inv * 2.0 * PI / h), sin(inv * 2.0 * PI / h));
        for (int j = 0; j < n; j += h)
        {
            cpx w(1, 0);
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)];
                a[k] = u + t;
                a[k + (h >> 1)] = u - t;
                w *= wn;
            }
        }
    }
    if (inv == -1)
        RP(i, 0, n)
        a[i] /= n;
}
void ntt(ll *a, int n, int inv = 1)
{
    ll u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        ll wn = ss(3, (mod - 1) / h);
        if (inv == -1)
            wn = ss(wn, mod - 2);
        for (int j = 0; j < n; j += h)
        {
            ll w = 1;
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)] % mod;
                a[k] = (u + t) % mod;
                a[k + (h >> 1)] = (u - t + mod) % mod;
                (w *= wn) %= mod;
            }
        }
    }
    if (inv == -1)
    {
        ll tmp = ss(n, mod - 2);
        RP(i, 0, n)
            (a[i] *= tmp) %= mod;
    }
}
struct Edge
{
    int u, v, nxt;
    //ll w;
    Edge(int _u = 0, int _v = 0, /*ll _w = 0,*/ int _nxt = 0)
    {
        u = _u;
        v = _v;
        //w = _w;
        nxt = _nxt;
    }

    /*int operator<(const Edge &b) const
    {
        return w < b.w;
    }*/
};
struct CMP
{
    int operator()(const int &a, const int &b) const
    {
        return a > b;
    }
};

const int maxn = 1e3 + 5;
/*------------------------------------------------------------------------yah01------------------------------------------------------------------------*/

int n;
char s[maxn];
vector<string> ans;
int main()
{
    int T;
    ru(T);
    rp(t, 1, T)
    {
        //srand(47);
        scanf("%s", s + 1);
        n = strlen(s + 1);
        //n = 1000;
        //rp(i, 2, n) s[i] = rand() % 10 + '0';
        //s[1] = rand() % 9 + 1 + '0';
        reverse(s + 1, s + n + 1);
        rp(i, 1, n)
        {
            s[i] = s[i] - '0';
        }
        printf("Case #%d:\n", t);

        ans.clear();
        string now;
        int x, cnt = 0;
        while (n)
        {
            int m = n / 2;
            int choice = 0;
            if (1)
            {
                if (n>=2 && s[n / 2 + 1] == 0)
                {
                    now.clear();
                    rp(i, 1, n / 2 + 1) now.push_back('1');
                }
                else
                {
                    rp(i, 1, m)
                    {
                        if (s[i] < s[n - i + 1]) break;
                        else if (s[i] > s[n - i + 1])
                        {
                            choice = 1;
                            break;
                        }
                    }

                    now.clear();
                    choice = 0;
                    if (n & 1)
                    {
                        if (n == 1)
                        {
                            now.push_back(s[1]+'0');
                        }
                        else
                        {
                            rp(i, 1, m) now.push_back(s[n - i + 1] + '0');
                            now.push_back(s[n / 2 + 1] - 1 + '0');
                            lp(i, m - 1, 0) now.push_back(now[i]);
                        }
                    }
                    else
                    {
                        if (n == 2)
                        {
                            int x = min(s[1], s[2]);
                            if (x)
                            {
                                now.push_back(x + '0');
                                now.push_back(x + '0');
                            }
                            else
                            {
                                now.push_back('1');
                            }
                        }
                        else
                        {
                            rp(i, 1, m - 1) now.push_back(s[n-i+1] + '0');
                            now.push_back(s[m + 1] - 1 + '0');
                            //now.push_back(s[m + 1] - 1 + '0');
                            lp(i, m-1, 0) now.push_back(now[i]);
                        }
                    }
                    
                }
            }
            else
            {
                now.clear();
                now.push_back(10 - s[n] + '0');
            }

            rp(i, 1, n)
            {
                if(i-1<now.length())
                    s[i] -= now[i - 1] - '0';
                while (s[i] < 0)
                {
                    s[i] += 10;
                    s[i + 1]--;
                }
            }

            while (n&&s[n] == 0) n--;
            ans.push_back(now);
        }
        
        int tot = ans.size();
        printf("%d\n", tot);
        RP(i, 0, tot)
        {
            int m = ans[i].length();
            RP(j, 0, m) printf("%c", ans[i][j]);
            putchar('\n');
        }
    }
    return 0;
}

/*
5
2 4 6 8 10
-1 2 2 2
1000
+ 1 10
+ 1 -2
+ 1 1
*/

G - Instability (cy&jmx)

題目來源:HDU-5917

03:28:07 通過(3次提交)

根據Ramsey定理,任意包含不少於$6$個點的集合,總會至少存在一個大小為$3$的團或者一個大小為$3$的獨立集。

這樣的話只要暴力枚舉小於$6$個點的集合的穩定性就行了,時間復雜度完全夠用。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
#include <complex>
#include <queue>
#include <algorithm>
#include <string>
#include <stack>
#include <bitset>
#include <cmath>
#include <set>

int N = 1e6, SZ = 320, INF = 1 << 29;
long long LINF = (1LL << 61), mod = 1e9 + 7;
const long double eps = 1e-9, PI = acos(-1.0);

#define lowbit(x) (x & (-(x)))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define rp(a, b, c) for (int a = b; a <= c; ++a)
#define RP(a, b, c) for (int a = b; a < c; ++a)
#define lp(a, b, c) for (int a = b; a >= c; --a)
#define LP(a, b, c) for (int a = b; a > c; --a)
#define rps(i, s) for (int i = 0; s[i]; i++)
#define fson(u) for (int i = g[u]; ~i; i = edg[i].nxt)
#define adde(u, v) edg[++ecnt] = Edge(u, v, 0, g[u]), g[u] = ecnt
#define addew(u, v, w) edg[++ecnt] = Edge(u, v, w, g[u]), g[u] = ecnt
#define MID (l + r >> 1)
#define mst(a, v) memset(a, v, sizeof(a))
#define bg(x)                Edge edg[maxn << x];     int g[maxn], ecnt
#define ex(v)      cout << v;     return 0
#define debug(x) cout << "debug: " << x << endl;
#define sqr(x) ((x) * (x))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef complex<double> cpx;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

char READ_DATA;
int SIGNAL_INPUT;
template <typename Type>
inline Type ru(Type &v)
{
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
        v = v * 10 + READ_DATA - '0';
    v *= SIGNAL_INPUT;
    return v;
}
inline ll modru(ll &v)
{
    ll p = 0;
    SIGNAL_INPUT = 1;
    while ((READ_DATA = getchar()) < '0' || READ_DATA > '9')
        if (READ_DATA == '-')
            SIGNAL_INPUT = -1;
        else if (READ_DATA == EOF)
            return EOF;
    p = v = READ_DATA - '0';
    while ((READ_DATA = getchar()) >= '0' && READ_DATA <= '9')
    {
        v = (v * 10 + READ_DATA - '0') % mod;
        p = (p * 10 + READ_DATA - '0') % (mod - 1);
    }
    v *= SIGNAL_INPUT;
    return p;
}
template <typename A, typename B>
inline int ru(A &x, B &y)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    return 2;
}
template <typename A, typename B, typename C>
inline int ru(A &x, B &y, C &z)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    return 3;
}
template <typename A, typename B, typename C, typename D>
inline int ru(A &x, B &y, C &z, D &w)
{
    if (ru(x) == EOF)
        return EOF;
    ru(y);
    ru(z);
    ru(w);
    return 4;
}
inline ll gcd(ll a, ll b)
{
    while (b)
    {
        a %= b;
        swap(a, b);
    }
    return a;
}

inline ll fastmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return (a * b - (ll)((long double)a * b / mod) * mod + mod) % mod;
}

inline ll dirmul(ll a, ll b, ll mod = 1e9 + 7)
{
    return a * b % mod;
}

inline ll ss(ll a, ll b, ll mod = 1e9 + 7, ll(*mul)(ll, ll, ll) = dirmul)
{
    if (b < 0)
    {
        b = -b;
        a = ss(a, mod - 2, mod);
    }
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans = mul(ans, a, mod);
        a = mul(a, a, mod);
        b >>= 1;
    }
    return ans;
}
inline int isprime(ll n)
{
    if (n == 1)
        return 0;

    for (ll d = 2; d * d <= n; ++d)
    {
        if (n % d == 0)
            return 0;
    }

    return 1;
}

template <typename Type>
void brc(Type *a, int n)
{
    int k;
    for (int i = 1, j = n / 2; i < n - 1; i++)
    {
        if (i < j)
            swap(a[i], a[j]);

        k = n >> 1;
        while (j >= k)
        {
            j ^= k;
            k >>= 1;
        }
        if (j < k)
            j ^= k;
    }
}
void fft(cpx *a, int n, int inv = 1)
{
    cpx u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        cpx wn(cos(inv * 2.0 * PI / h), sin(inv * 2.0 * PI / h));
        for (int j = 0; j < n; j += h)
        {
            cpx w(1, 0);
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)];
                a[k] = u + t;
                a[k + (h >> 1)] = u - t;
                w *= wn;
            }
        }
    }
    if (inv == -1)
        RP(i, 0, n)
        a[i] /= n;
}
void ntt(ll *a, int n, int inv = 1)
{
    ll u, t;
    brc(a, n);
    for (int h = 2; h <= n; h <<= 1)
    {
        ll wn = ss(3, (mod - 1) / h);
        if (inv == -1)
            wn = ss(wn, mod - 2);
        for (int j = 0; j < n; j += h)
        {
            ll w = 1;
            for (int k = j; k < j + (h >> 1); k++)
            {
                u = a[k];
                t = w * a[k + (h >> 1)] % mod;
                a[k] = (u + t) % mod;
                a[k + (h >> 1)] = (u - t + mod) % mod;
                (w *= wn) %= mod;
            }
        }
    }
    if (inv == -1)
    {
        ll tmp = ss(n, mod - 2);
        RP(i, 0, n)
            (a[i] *= tmp) %= mod;
    }
}
struct Edge
{
    int u, v, nxt;
    //ll w;
    Edge(int _u = 0, int _v = 0, /*ll _w = 0,*/ int _nxt = 0)
    {
        u = _u;
        v = _v;
        //w = _w;
        nxt = _nxt;
    }

    /*int operator<(const Edge &b) const
    {
        return w < b.w;
    }*/
};
struct CMP
{
    int operator()(const int &a, const int &b) const
    {
        return a > b;
    }
};

const int maxn = 1e3 + 5;
/*------------------------------------------------------------------------yah01------------------------------------------------------------------------*/

int n, m;
int f[51][51], g[51][51][51];
int main()
{
    int T;
    ru(T);
    rp(t, 1, T)
    {
        mst(f, 0);
        mst(g, 0);
        ru(n, m);
        while (m--)
        {
            int u, v;
            ru(u, v);
            f[u][v] = f[v][u] = 1;
        }

        ll ans = 0, tot = ss(2, n);
        tot -= (1 + n + n * (n - 1)*ss(2,mod-2)) % mod;
        if (tot < 0) tot += mod;

        rp(i, 1, n)
        {
            rp(j, i + 1, n)
            {
                rp(k, j + 1, n)
                {
                    if ((f[i][j] && f[i][k] && f[j][k]) || (!f[i][j] && !f[i][k] && !f[j][k]))
                    {
                        ++ans;
                        g[i][j][k] = 1;
                    }
                    --tot;
                    if (tot < 0) tot += mod;
                }
            }
        }

        rp(i, 1, n)
        {
            rp(j, i + 1, n)
            {
                rp(k, j + 1, n)
                {
                    rp(p, k + 1, n)
                    {
                        if (g[i][j][k] || g[i][j][p] || g[j][k][p] || g[i][k][p])
                        {
                            ++ans;
                            if (ans >= mod) ans -= mod;
                        }
                        --tot;
                        if (tot < 0) tot += mod;
                    }
                }
            }
        }

        rp(i, 1, n)
        {
            rp(j, i + 1, n)
            {
                rp(k, j + 1, n)
                {
                    rp(p, k + 1, n)
                    {
                        rp(q, p + 1, n)
                        {
                            if (g[i][j][k] || g[i][j][p] || g[i][j][q] || g[i][k][p]||g[i][k][q] || g[i][p][q] || g[j][k][p] || g[j][k][q] || g[j][p][q] || g[k][p][q])
                            {
                                ++ans;
                                if (ans >= mod) ans -= mod;
                            }
                            --tot;
                            if (tot < 0) tot += mod;
                        }
                    }
                }
            }
        }

        ans += tot;
        ans %= mod;
        printf("Case #%d: %lld\n", t, ans);
    }
    return 0;
}

/*
5
2 4 6 8 10
-1 2 2 2
1000
+ 1 10
+ 1 -2
+ 1 1
*/

E - The Fastest Runner Ms. Zhang (jmx賽後補題)

題目來源:HDU-5917

賽後補題

顯然這是一個環套樹的問題。

定義$dis_{u,v}$為$u$和$v$的距離。定義$len$為環的長度。定義$mxdep_u$為以環上的點$u$為根的樹的最深深度。以$2n$為初始標準,對於我們選定的點對$(S,T)$,有如下兩種情況:

  1. 如果$(S,T)$在同一顆子樹中,那麽答案就是$2n-len-dis_{S,T}$
  2. 如果$(S,T)$不在同一顆子樹中,令$S$和$T$所在的樹的根分別為$U$和$V$,那麽答案就是$2n-mxdep_S-mxdep_T-dis_{U,V}(取環上較長的路徑)-2$

從兩種方法中取最大值就行了。前一類是經典問題,後一類可以將mxdep全部求出,然後將環復制兩份變成鏈,用單調隊列或者線段樹處理(忘了單調隊列怎麽寫所以寫的線段樹)。不過輸出方案很麻煩。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x6fffffff
#define N 200086
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,ans,ansx,ansy;
int inl[N],vis[N],head[N],dep[N],mxdep[N],v[N];
int q[N*2],nxt[N*2];
int p[N];
int tt;
bool flag;
int len;
int l[N];
int f[N*4];
void clr()
{
    ans=tt=flag=len=0;
    for(int i=1;i<=n;i++)head[i]=vis[i]=inl[i]=dep[i]=mxdep[i]=0;
}
void ins(int u,int v){q[++tt]=v;nxt[tt]=head[u];head[u]=tt;}
void findcircle(int i,int pre)
{
    vis[i]=1;p[i]=pre;
    for(int j=head[i];j;j=nxt[j])
        if(q[j]!=pre)
        {
            if(vis[q[j]])
            {
                for(int x=i;x!=q[j];x=p[x]){inl[x]=1;l[++len]=x;}
                l[++len]=q[j];inl[q[j]]=1;
                flag=1;return;
            }
            else findcircle(q[j],i);
            if(flag)return;
        }
}
void update(int tmp,int x,int y)
{
    if(x>y)swap(x,y);
    if(tmp<ans)return;
    if(tmp>ans)
    {
        ans=tmp;ansx=x;ansy=y;
    }
    else
    {
        if(x>ansx)return;
        if(x<ansx)
        {
            ansx=x;ansy=y;
        }
        else{
            if(y<ansy)ansy=y;
        }
    }
}
void dfs(int i,int ro,int pre)
{
    mxdep[i]=i;
    int id=i;
    for(int j=head[i];j;j=nxt[j])
        if(!inl[q[j]]&&q[j]!=pre)
        {
            dep[q[j]]=dep[i]+1;dfs(q[j],ro,i);
            int tmp=dep[id]+dep[mxdep[q[j]]]-2*dep[i];
            update(tmp+len,mxdep[q[j]],id);
            if(dep[mxdep[q[j]]]>dep[id]||(dep[mxdep[q[j]]]==dep[id]&&mxdep[q[j]]<id))id=mxdep[q[j]];
        }
    mxdep[i]=id;
}
int findmn(int a,int b)
{
    if(a==0||b==0)return a+b;
    if(v[a]<v[b])return a;
    if(v[a]>v[b])return b;
    if(mxdep[l[a]]<mxdep[l[b]])return a;else return b;
}
void build(int i,int l,int r)
{
    if(l==r){f[i]=l;return;}
    int mid=(l+r)/2;
    build(i*2,l,mid);build(i*2+1,mid+1,r);
    f[i]=findmn(f[i*2],f[i*2+1]);
}
int ask(int i,int l,int r,int lt,int rt)
{
    if(lt<=l&&r<=rt)return f[i];
    int mid=(l+r)/2,res=0;
    if(lt<=mid)res=findmn(res,ask(i*2,l,mid,lt,rt));
    if(mid+1<=rt)res=findmn(res,ask(i*2+1,mid+1,r,lt,rt));
    return res;
}
int main()
{
    int T=read();
    for(int cas=1;cas<=T;cas++)
    {
        n=read();
        clr();
        for(int i=1;i<=n;i++)
        {
            int u=read(),v=read();
            ins(u,v);ins(v,u);
        }
        findcircle(1,0);
        for(int i=1;i<=n;i++)
            if(inl[i]){mxdep[i]=i;dfs(i,i,0);}
        //for(int i=1;i<=len;i++)printf("%d %d\n",l[i],mxdep[l[i]]);
        for(int i=1;i<=len;i++)l[i+len]=l[i];
        len*=2;
        for(int i=1;i<=len;i++)v[i]=i-dep[mxdep[l[i]]];
        build(1,1,len);
        for(int i=2;i<=len;i++)
        {
            int tmp=i+dep[mxdep[l[i]]]+2;
            int id=ask(1,1,len,max(1,i-len/2+1),i-1);
            update(tmp-v[id],mxdep[l[id]],mxdep[l[i]]);
        }
        printf("Case #%d: %d %d %d\n",cas,2*n-ans,ansx,ansy);
    }
    return 0;
}

K - Binary Indexed Tree (jmx賽後補題)

題目來源:HDU-5921

賽後補題

對於每一個數計算貢獻,即這個數被really change了多少次。顯然,不以某個數為前綴的數對個數即為這個點的貢獻。對於一個數$x$,如果在$n$以內的以$x$為前綴的數的個數為$t$,那麽對答案的貢獻就是$t \times (n-t+1)$。

對於大多數數字,$t$的取值都是$2^j$。可以使用數位dp來統計這種情況。$f_{i,j,k}$表示$i$位二進制數結尾有恰好$j$個$0$並且最高位為$k$的二進制數個數。這樣的話用一個普通數位dp就能統計出來$t$取值為$2^j$的數的個數,然後統一算貢獻。


那些$t$的取值不是$2$的次冪的數,一定是$n$的前綴。對於$n$的前綴$x$,$t=n-x+1$。把這種情況再算一下加起來就好。

#include <bits/stdc++.h>
#define MOD 1000000007
#define inf 0x6fffffff
using namespace std;
typedef long long ll;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll f[61][61][2],bin[61];
void pre()
{
    bin[0]=1;
    for(int i=1;i<=60;i++)bin[i]=(bin[i-1]<<1)%MOD;
    for(int i=1;i<=60;i++)
    {
        for(int j=0;j<=i-2;j++)
        {
            f[i][j][0]=bin[i-j-2];
            f[i][j][1]=bin[i-j-2];
        }
        f[i][i-1][1]=1;
        f[i][i][0]=1;
    }
}
ll calc(ll n)
{
    int num[61],cnt=0;
    ll x=n;
    while(x)
    {
        num[++cnt]=x&1;x>>=1;
    }
    ll ans=0;
    n%=MOD;
    for(int k=0;k<=cnt;k++)
    {
        ll res=0;
        for(int i=1;i<cnt;i++)res=(res+f[i][k][1])%MOD;
        for(int i=cnt-1;i;i--)
        {
            if(num[i]==1)
            {
                if(k<i-1)res=(res+f[i][k][0])%MOD;
            }
        }
        res=res*(bin[k]*((n+1-bin[k])%MOD)%MOD)%MOD;
        ans=(ans+res)%MOD;
    }
    ll tmp=(1LL<<(cnt-1))%MOD;
    for(int i=cnt-1;i;i--)
    {
        if(num[i+1])ans=(ans+(n-tmp+1)*(n+1-(n-tmp+1))%MOD)%MOD;
        tmp=(tmp+num[i]*(1LL<<(i-1))%MOD)%MOD;
    }
    if(num[1])ans+=n;
    return (ans+MOD)%MOD;
}
int main()
{
    pre();
    int T=read();
    for(int cas=1;cas<=T;cas++)
    {
        ll n=read();
        printf("Case #%d: ",cas);
        cout<<calc(n)<<endl;
    }
    return 0;
}

ccpc 2016 changchun 長春(4.12訓練)