放在前面的..
傻逼呵呵蒟蒻没事做百度之星..
比赛感悟啦啦啦..
这比赛和HWizard一起做啊…
一开始服务器爆炸.. 一直登不上去.. 我tm就是可以上,还傻逼呵呵的给UOJ群发题目
直到大家都可以上的时候才开始做,一看ranklist,在群上一言不发的吉司机早已做了一题.. 而且还有很多人都做了第一题.. 开始看题0.0..
啊第一题什么.. 啊第二题什么.. 啊.. 真的是too naive啊.. 一题都不会做啊..
然后HWizard大神突然爆出一句,啊第一题不是矩乘吗?然后傻逼的我恍然大悟,开始码代码.. 打出来又调啊调.. 最后发现转移矩阵输反了又改改改.. 好吧A了..
然而大神还在狂TLE不止.. 我就去看了比较多人AC的1006,在纸上画了画,又画了画.. 哎这不是拓扑图吗?看看优先级.. 这不是很水吗..
随手来了一发n^2的做法.. 很成功TLE了..
改了个堆优化做法.. 很成功WA了..
再改了个long long.. 很成功AC了..
突然想起某神犇说的【OI成绩=实力+经验..】 真的是too naive啊..
接着就看1002啊,明显的状态压缩..想到一个做法.. 但是被HWizard打消了..然后就没打.. 那么就打1005咯.. 哎这规律有点明显诶.. 码代码0.0..
一次WA.. 两次WA.. 哎快结束了.. 然而考完试的la1la1la看了一下,这1003不是大水题吗?这不是裸题吗?我一看,卧槽这么水的我怎么没看这道题啊..
5min.. 算了放弃0.0..
非常好的拿了个rank610.. 明天再打咯.. too navie啊..
傻逼呵呵的我还涨了170+的rating.. 基础分太低了..
题解一发..
1001
用矩阵乘法求出这个数.. 然后再检验是否符合条件就好了..
code
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct node {
int a[2][2];
int l1, l2;
node (){
memset ( a, 0, sizeof (a) );
}
}trans, x, z, one;
int X, m, c, K;
node ttimes ( node x, node y ){
node ret;
ret.l1 = x.l1; ret.l2 = y.l2;
int i, j, k;
for ( i = 0; i <= ret.l1; i ++ ){
for ( j = 0; j <= ret.l2; j ++ ){
for ( k = 0; k <= x.l2; k ++ ){
ret.a[i][j] = ( ret.a[i][j] + (x.a[i][k]*y.a[k][j])%K ) % K;
}
}
}
return ret;
}
int main (){
int i, j;
int T, Ti;
Ti = 0;
trans.l1 = trans.l2 = 1;
trans.a[0][0] = 10; trans.a[0][1] = 0;
trans.a[1][0] = 1; trans.a[1][1] = 1;
one.l1 = one.l2 = 1;
one.a[0][0] = 1; one.a[0][1] = 0;
one.a[1][0] = 0; one.a[1][1] = 1;
scanf ( "%d", &T );
while ( T -- ){
scanf ( "%d%d%d%d", &X, &m, &K, &c );
x = trans;
z = one;
node p;
p.l1 = 0; p.l2 = 1;
p.a[0][0] = 0; p.a[0][1] = X;
for ( i = m; i >= 1; i >>= 1 ){
if ( i & 1 ) z = ttimes ( z, x );
x = ttimes ( x, x );
}
p = ttimes ( p, z );
printf ( "Case #%d:\n", ++Ti );
if ( p.a[0][0] % K == c ) printf ( "Yes\n" );
else printf ( "No\n" );
}
return 0;
}
1002
用f[i][j][k]表示第i个数,前一个数是j,可以选的数的集合状态k,然后就递推啦啦啦..
1003
从0开始,就把0作根拉成一棵树.. 因为要经过x,所以我们可以到达所有x子树上的点.. 那么就裸的dfs序+线段树维护个最大值即可.. 注意防爆栈..
1004
神奇的题目,我现在还没看过题..
1005
s1=B
s2=BBD
s3=BBDBBDD
s4=BBDBBDDBBBDDBDD
看一下s3和s4
s3=BBDBBDD
s4=|BBDBBDD|B|BBDDBDD|
=s3|B|BBD|D|BDD|
=s3|B|s2|D|B|D|D|
=s3|B|s2|D|s1|D|D|
其实再推多几个就可以发现其实可以分成若干个上串.. 而且除了这些串绝对没有别的B.. 那么就一个个2的几次方减一下再累加一下.. 最后再加1就好了..
由于我WA了.. 真的不知道这个做法是不是正确的..
1006
就tm是个拓扑图..
我们可以看出这个队列答案数组是单调不上升的.. 那么假如对于两个数,我可以把它们两个互换位置的话,那肯定是大的在前面.. 记住要long long啊..
code
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;
const LL Maxn = 110000;
LL ind[Maxn], n, m;
struct node {
LL y, next;
}a[Maxn]; LL first[Maxn], len;
void ins ( LL x, LL y ){
len ++;
a[len].y = y;
a[len].next = first[x]; first[x] = len;
}
bool v[Maxn];
LL _min ( LL x, LL y ){ return x < y ? x : y; }
priority_queue <LL> q;
int main (){
LL i, j, k, T;
scanf ( "%I64d", &T );
while ( T -- ){
scanf ( "%I64d%I64d", &n, &m );
memset ( ind, 0, sizeof (ind) );
len = 0; memset ( first, 0, sizeof (first) );
for ( i = 1; i <= m; i ++ ){
LL x, y;
scanf ( "%I64d%I64d", &x, &y );
ins ( x, y ); ind[y] ++;
}
for ( i = 1; i <= n; i ++ ){
if ( ind[i] == 0 ) q.push (i);
}
LL ans = 0;
memset ( v, false, sizeof (v) );
LL minn = n;
for ( i = 1; i <= n; i ++ ){
LL p = q.top (); q.pop ();
v[p] = true;
minn = _min ( minn, p );
ans += minn;
for ( k = first[p]; k; k = a[k].next ){
LL y = a[k].y;
ind[y] --;
if ( ind[y] == 0 ) q.push (y);
}
}
printf ( "%I64d\n", ans );
}
return 0;
}
最后再说几句
由于比赛经验真的不够.. 很多细节的东西还是没注意到导致罚时爆炸..
还是要努力训练啊..