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\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次提交)
通过观察可以得出:
- $P_i,P_{i-1}$一个是奇数一个是偶数时,$gcd(P_i,P_{i-1})=1$
- $P_i,P_{i-1}$为连续的奇数时,$gcd(P_i,P_{i-1})=1$
- $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)$,有如下两种情况:
- 如果$(S,T)$在同一颗子树中,那么答案就是$2n-len-dis_{S,T}$
- 如果$(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$的取值都是$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;
}