zoukankan      html  css  js  c++  java
  • 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;
    }
    

  • 相关阅读:
    Fidder4 顶部提示 “The system proxy was changed,click to reenable fiddler capture”。
    redis 哨兵 sentinel master slave 连接建立过程
    虚拟点赞浏览功能的大数据量测试
    python基础练习题(题目 字母识词)
    python基础练习题(题目 回文数)
    python基础练习题(题目 递归求等差数列)
    python基础练习题(题目 递归输出)
    python基础练习题(题目 递归求阶乘)
    python基础练习题(题目 阶乘求和)
    python基础练习题(题目 斐波那契数列II)
  • 原文地址:https://www.cnblogs.com/oldjang/p/10657796.html
Copyright © 2011-2022 走看看