• ccpc 2016 changchun 长春(4.12训练)


    概述

    训练来源: 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
    ", 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
    ",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
    ",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
    ", 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 floor$个数的位置就行了。

    #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:
    ", 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
    ", tot);
    		RP(i, 0, tot)
    		{
    			int m = ans[i].length();
    			RP(j, 0, m) printf("%c", ans[i][j]);
    			putchar('
    ');
    		}
    	}
    	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
    ", 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
    ",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
    ",cas,2*n-ans,ansx,ansy);
        }
        return 0;
    }
    

    K - Binary Indexed Tree (jmx赛后补题)

    题目来源:HDU-5921

    赛后补题

    对于每一个数计算贡献,即这个数被really change了多少次。显然,不以某个数为前缀的数对个数即为这个点的贡献。对于一个数$x$,如果在$n$以内的以$x$为前缀的数的个数为$t$,那么对答案的贡献就是$t imes (n-t+1)$。

    对于大多数数字,$t$的取值都是$2j$。可以使用数位dp来统计这种情况。$f_{i,j,k}$表示$i$位二进制数结尾有恰好$j$个$0$并且最高位为$k$的二进制数个数。这样的话用一个普通数位dp就能统计出来$t$取值为$2j$的数的个数,然后统一算贡献。


    那些$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;
    }
    

  • 相关阅读:
    静态INCLUDE与动态INCLUDE的区别
    SQL注入
    SpringMVC
    设计模式—七大原则
    Demo小细节-2
    Java运算符
    Java内部类的基本解析
    接口类和抽象类
    Statement和PreparedStatement
    ArrayList,LinkedLIst,HashMap
  • 原文地址:https://www.cnblogs.com/oldjang/p/10657796.html
Copyright © 2020-2023  润新知