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$的取值都是$2^j$。可以使用數位dp來統計這種情況。$f_{i,j,k}$表示$i$位二進制數結尾有恰好$j$個$0$並且最高位為$k$的二進制數個數。這樣的話用一個普通數位dp就能統計出來$t$取值為$2^j$的數的個數,然後統一算貢獻。
那些$t$的取值不是$2$的次冪的數,一定是$n$的前綴。對於$n$的前綴$x$,$t=n-x+1$。把這種情況再算一下加起來就好。
#include <bits/stdc++.h>
#define MOD 1000000007
#define inf 0x6fffffff
using namespace std;
typedef long long ll;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll f[61][61][2],bin[61];
void pre()
{
bin[0]=1;
for(int i=1;i<=60;i++)bin[i]=(bin[i-1]<<1)%MOD;
for(int i=1;i<=60;i++)
{
for(int j=0;j<=i-2;j++)
{
f[i][j][0]=bin[i-j-2];
f[i][j][1]=bin[i-j-2];
}
f[i][i-1][1]=1;
f[i][i][0]=1;
}
}
ll calc(ll n)
{
int num[61],cnt=0;
ll x=n;
while(x)
{
num[++cnt]=x&1;x>>=1;
}
ll ans=0;
n%=MOD;
for(int k=0;k<=cnt;k++)
{
ll res=0;
for(int i=1;i<cnt;i++)res=(res+f[i][k][1])%MOD;
for(int i=cnt-1;i;i--)
{
if(num[i]==1)
{
if(k<i-1)res=(res+f[i][k][0])%MOD;
}
}
res=res*(bin[k]*((n+1-bin[k])%MOD)%MOD)%MOD;
ans=(ans+res)%MOD;
}
ll tmp=(1LL<<(cnt-1))%MOD;
for(int i=cnt-1;i;i--)
{
if(num[i+1])ans=(ans+(n-tmp+1)*(n+1-(n-tmp+1))%MOD)%MOD;
tmp=(tmp+num[i]*(1LL<<(i-1))%MOD)%MOD;
}
if(num[1])ans+=n;
return (ans+MOD)%MOD;
}
int main()
{
pre();
int T=read();
for(int cas=1;cas<=T;cas++)
{
ll n=read();
printf("Case #%d: ",cas);
cout<<calc(n)<<endl;
}
return 0;
}
ccpc 2016 changchun 長春(4.12訓練)