刷完了HNOI[2008],来写个题解吧。
Cards
#include <cstdio>
#include <vector>
#include <cstring>
#define pb push_back
using namespace std;
const int MAXM = 69;
const int MAXC = 29;
int sr;
int sg;
int sb;
int m;
int p;
int n;
vector<int> cir[MAXM];
int ans;
int f[MAXC][MAXC][MAXC];
inline int adv(int m, int p)
{
int re = 1, base = m;
int tp = p-2;
while(tp)
{
if(tp&1) re = re*base%p;
tp >>= 1;
base = base*base%p;
}
return re;
}
int main()
{
scanf("%d%d%d%d%d", &sr, &sg, &sb, &m, &p);
n = sr+sg+sb;
for(int i = 1; i <= m; ++i)
{
int g[MAXM] = {0};
bool vis[MAXM] = {false};
for(int j = 1; j <= n; ++j)
scanf("%d", g+j);
for(int j = 1; j <= n; ++j)
if(!vis[j])
{
int sum = 0;
int k = j;
while(!vis[k])
{
sum++;
vis[k] = true;
k = g[k];
}
cir[i].pb(sum);
}
}
m++;
for(int i = 1; i <= n; ++i)
cir[m].pb(1);
for(int i = 1; i <= m; ++i)
{
memset(f, 0, sizeof(f));
f[0][0][0] = 1;
for(int j = 1, sz = cir[i].size(); j <= sz; ++j)
{
int w = cir[i][j-1];
for(int r = sr; r >= 0; --r)
for(int g = sg; g >= 0; --g)
for(int b = sb; b >= 0; --b)
{
if(r >= w) f[r][g][b] += f[r-w][g][b];
if(g >= w) f[r][g][b] += f[r][g-w][b];
if(b >= w) f[r][g][b] += f[r][g][b-w];
f[r][g][b] %= p;
}
}
ans = (ans+f[sr][sg][sb])%p;
}
ans = ans*adv(m, p)%p;
printf("%d", ans);
return 0;
}
明明的烦恼
题解请走这里:
http://www.cnblogs.com/zhj5chengfeng/p/3278557.html
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1009;
const int MAXL = 1009;
int n;
int d[MAXN];
int sum;
int cnt;
struct bi
{
int len;
int a[MAXL];
inline void reset(int k)
{
len = 0;
memset(a, 0, sizeof(a));
a[++len] = k;
}
inline void operator *= (int k)
{
for(int i = 1; i <= len; ++i)
a[i] *= k;
for(int i = 1; i <= len; ++i)
{
a[i+1] += a[i]/10000;
a[i] %= 10000;
}
while(a[len+1])
{
len++;
a[len+1] += a[len]/10000;
a[len] %= 10000;
}
}
inline void operator /= (int k)
{
for(int i = len; i >= 1; --i)
{
a[i-1] += a[i]%k*10000;
a[i] /= k;
}
while(!a[len])
len--;
}
inline void print()
{
printf("%d", a[len]);
for(int i = len-1; i >= 1; --i)
printf("%04d", a[i]);
}
}ans;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
scanf("%d", d+i);
if(d[i] != -1)
{
cnt++;
sum += d[i]-1;
}
}
ans.reset(1);
for(int i = n-2; i > n-2-sum; --i)
ans *= i;
for(int i = 1; i <= n; ++i)
if(d[i] != -1)
for(int j = 2; j < d[i]; ++j)
ans /= j;
for(int i = 1; i <= n-2-sum; ++i)
ans *= (n-cnt);
ans.print();
puts("");
return 0;
}
神奇的国度
基础知识请走这里:
http://blog.youkuaiyun.com/qq_20118433/article/details/44420099
完美消除序列从后往前依次给每个点染色,给每个点染上可以染的最小的颜色。
证明:
设使用
T
种颜色, 则
T=
团数
≤
色数
团数 = 色数 =
T
时间复杂度:
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int MAXN = 10009, MAXM = 1000009;
int n, m;
inline int readi()
{
int re = 0;
bool flag = false;
char c = getchar();
while(1)
{
if(c >= '0' && c <= '9')
{
re = re*10+c-'0';
flag = true;
}
else
if(flag) return re;
c = getchar();
}
}
struct Graph
{
int p;
int head[MAXN];
int v[MAXM<<1];
int ne[MAXM<<1];
Graph(){p = 1;}
inline void add(int u, int vv)
{
v[p] = vv;ne[p] = head[u];
head[u] = p++;
}
}E;
int seg[MAXN];
bool vis[MAXN];
int col[MAXN];
int hash[MAXN];
int Max = 1;
int ans;
struct List
{
int id;
List *ne, *fr;
}*label[MAXN] = {NULL}, *tail[MAXN] = {NULL}, null = {0, NULL, NULL};
int line[MAXN];
List *place[MAXN];
inline void ins(int i, int p)
{
List *pre = tail[i]->fr, *bac = tail[i], *now;
now = (List *)malloc(sizeof(List));
*now = null;now->id = p;
pre->ne = now;now->fr = pre;
bac->fr = now;now->ne = bac;
place[p] = now;
line[p] = i;
}
inline void del(List *now)
{
List *pre = now->fr, *bac = now->ne;
pre->ne = bac;bac->fr = pre;
line[now->id] = 0;
place[now->id] = NULL;
free(now);
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i)
{
int u, v;
u = readi();
v = readi();
E.add(u, v);E.add(v, u);
}
for(int i = 1; i <= n; ++i)
{
label[i] = (List *)malloc(sizeof(List));
*label[i] = null;
label[i]->ne = (List *)malloc(sizeof(List));
*label[i]->ne = null;
tail[i] = label[i]->ne;
label[i]->ne = tail[i];
tail[i]->fr = label[i];
ins(1, i);
}
for(int i = n; i >= 1; --i)
{
List *p;
for(List *j = label[Max]->ne; ;)
{
while(j == tail[Max]) j = label[--Max]->ne;
if(vis[j->id])
{
List *tmp = j->ne;
del(j);
j = tmp;
}
else
{
p = j;
break;
}
}
seg[i] = p->id;
vis[p->id] = true;
for(int j = E.head[p->id]; j; j = E.ne[j])
if(!vis[E.v[j]])
{
int row = line[E.v[j]];
ins(row+1, E.v[j]);
if(Max < row+1) Max = row+1;
}
del(p);
}
memset(vis+1, false, n*sizeof(bool));
for(int i = n; i >= 1; --i)
{
vis[seg[i]] = true;
col[seg[i]] = 1;
for(int j = E.head[seg[i]]; j; j = E.ne[j])
if(vis[E.v[j]])
hash[col[E.v[j]]] = i;
for(int j = 1; j <= n; ++j)
if(hash[j] != i)
{
col[seg[i]] = j;
break;
}
if(col[seg[i]] > ans) ans = col[seg[i]];
}
printf("%d\n", ans);
return 0;
}
水平可见直线
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define sqr(x) ((x)*(x))
using namespace std;
const int maxn = 50009;
const double eps = 1e-8;
int n;
struct Line
{
int id;
double k, b;
}line[maxn];
int top;
Line stack[maxn];
bool visable[maxn];
inline bool cmpk(const Line &a, const Line &b)
{
if(fabs(a.k-b.k) <= eps) return a.b < b.b;
else return a.k < b.k;
}
inline double interx(const Line &a, const Line &b)
{
return (b.b-a.b)/(a.k-b.k);
}
inline void insert(const Line &a)
{
while(top)
{
Line t = stack[top], t_1 = stack[top-1];
if(fabs(a.k-t.k) <= eps) --top;
else if(top > 1 && interx(a, t) <= interx(t, t_1)) --top;
else break;
}
stack[++top] = a;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
scanf("%lf%lf", &line[i].k, &line[i].b);
line[i].id = i;
}
sort(line+1, line+n+1, cmpk);
for(int i = 1; i <= n; ++i)
insert(line[i]);
for(int i = 1; i <= top; ++i)
visable[stack[i].id] = true;
for(int i = 1; i <= n; ++i)
if(visable[i]) printf("%d ", i);
return 0;
}
越狱
#include <iostream>
const int mod = 100003;
inline int power(int a, long long b)
{
int re = 1, base = a;
while(b)
{
if(b&1) re = (long long)re*base%mod;
base = (long long)base*base%mod;
b >>= 1;
}
return re;
}
int main()
{
int m = 0;
long long n = 0;
std::cin >> m >> n;
m %= mod;
std::cout << (power(m, n)-(long long)m*power(m-1, n-1)%mod+mod)%mod << std::endl;
return 0;
}
GT考试
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int maxm = 29;
int n, m, mod;
string a;
int f[maxm];
struct mtx
{
int g[maxm][maxm];
mtx(){memset(g, 0, sizeof(g));}
inline mtx operator * (const mtx &a)
{
mtx b;
for(int i = 0; i < m; ++i)
for(int j = 0; j < m; ++j)
for(int k = 0; k < m; ++k)
b.g[i][j] = (b.g[i][j]+g[i][k]*a.g[k][j]%mod)%mod;
return b;
}
}M, ans;
int main()
{
cin >> n >> m >> mod >> a;
for(int i = 1; i < m; ++i)
{
int j = f[i];
while(j && a[j] != a[i]) j = f[j];
f[i+1] = a[j]==a[i] ? j+1 : 0;
}
for(int i = 0; i < m; ++i)
for(int j = '0'; j <= '9'; ++j)
{
if((char)j == a[i]) M.g[i][i+1]++;
else
{
int k = i;
while(k && a[k] != (char)j) k = f[k];
if(a[k] == (char)j) k++;
M.g[i][k]++;
}
}
for(int i = 0; i < m; ++i)
ans.g[i][i] = 1;
int b = n;
while(b)
{
if(b&1) ans = ans*M;
M = M*M;
b >>= 1;
}
int sum = 0;
for(int i = 0; i < m; ++i)
sum = (sum+ans.g[0][i])%mod;
cout << sum << endl;
return 0;
}
玩具装箱toy
#include <cstdio>
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long LL;
const int maxn = 50009;
int n, L;
LL c[maxn];
LL sum[maxn];
LL f[maxn];
int q[maxn];
int l, r;
#define T(p) (sum[p]+p)
#define X(p) (T(p)<<1)
#define Y(p) (f[p]+sqr(T(p)+L+1))
int main()
{
scanf("%d%d", &n, &L);
for(int i = 1; i <= n; ++i)
{
scanf("%lld", c+i);
sum[i] = sum[i-1]+c[i];
}
for(int i = 1; i <= n; ++i)
{
while(l <= r-1 && Y(q[l+1])-Y(q[l]) <= T(i)*(X(q[l+1])-X(q[l])))
q[l++] = 0;
f[i] = f[q[l]]+sqr(i-q[l]-1+sum[i]-sum[q[l]]-L);
while(l <= r && (Y(i)-Y(q[r]))*(X(i)-X(q[r-1])) < (Y(i)-Y(q[r-1]))*(X(i)-X(q[r])))
q[r--] = 0;
q[++r] = i;
}
printf("%lld\n", f[n]);
return 0;
}
遥远的行星
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 100009;
const double eps = 1e-6;
int n;
double a;
double m[maxn];
double sum[maxn];
int main()
{
scanf("%d%lf", &n, &a);
for(int i = 1; i <= n; ++i)
{
scanf("%lf", m+i);
sum[i] = sum[i-1]+m[i];
}
for(int i = 1; i <= n; ++i)
{
int k = a*i;
double f = 0;
if(fabs((k+1)*1.0-a*i) <= eps) k++;
if(k <= 50)
for(int j = 1; j <= k; ++j)
f += m[i]*m[j]/(double)(i-j);
else f = sum[k]*m[i]/(double)(i-((1+k)>>1));
printf("%lf\n", f);
}
return 0;
}
差不多就是这样了,HNOI[2009]走起…