JAG Practice Contest 2011
Japanese Alumni Group
Solution
Problem A: InfinityMaze
Problem B:Butterfly
Problem C:Chinese Classics
Problem D: Revengeof Champernowne Constant
Problem E: Full Text Search
Problem F:Mysterious Maze
Problem G:Number Sorting
Problem H: SkyJump
Problem I: MobileNetwork
Problem J: BlueForest
April 27th,2013 by chlxyd
Aizu2320~2329
Problem A: InfinityMaze(E)
给个n*m的迷宫,给个机器人,机器人有面相的方向,每次机器人往前走,如果不能走了就往右转,问k步之后会到达哪个位置,面相哪里。(k<=10^18)。
Solution
Tag:模拟
模拟机器人的走路,记录到达每个格子的最早步数,当第二次到达某个格子的时候,表示形成了一个循环,我们可以算出循环节的长度,用k去模,对于余数继续模拟,直到走到最后的格子。
有个需要注意的地方就是方向,进入某个格子的方向和从这个格子走出去的方向可能是不一样的,要得到进入某个格子的方向,我们只需要先走k-1步,然后看现在走出的方向就可以了。
/*
* Author: chlxyd
* Created Time: 2013/4/25 12:20:44
* File Name: A.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
int jl[110][110][5] ;
int w[110][110][5] ;
int last[110][110] ;
int n , m ;
long long l ;
bool flag ;
char s[110][110] ;
struct grid {
int x , y , way ;
void right() {
way ++ ;
if ( way == 5 ) way = 1 ;
}
}p ;
grid next( grid p ) {
grid ret = p ;
if ( ret.way == 1 ) ret.y -- ;
else if ( ret.way == 2 ) ret.x -- ;
else if ( ret.way == 3 ) ret.y ++ ;
else if ( ret.way == 4 ) ret.x ++ ;
return ret ;
}
char change( int x ) {
if ( x == 1 ) return 'W' ;
if ( x == 2 ) return 'N' ;
if (x == 3 ) return 'E' ;
if ( x == 4 ) return 'S' ;
}
int cal( char c ) {
if ( c == 'W' ) return 1 ;
if ( c == 'N' ) return 2 ;
if (c == 'E' ) return 3;
if ( c == 'S' ) return 4 ;
}
void move() {
grid now = next( p ) ;
flag = false ;
if ( now.x <= 0 || now.x > n || now.y <= 0 || now.y > m || s[now.x][now.y] == '#' ) {
p.right() ; return ;
}
flag = true ;
p = now ;
return ;
}
void bfs( int i , int j , int way , long long step ) {
p.x = i ; p.y = j ; p.way = way ; jl[i][j][way] = 1 ; w[i][j][way] = step ;
while ( true ) {
move() ;
if ( flag )
step ++ ;
if ( jl[p.x][p.y][p.way] == 1 )
break ;
jl[p.x][p.y][p.way] = 1 ;
w[p.x][p.y][p.way] = step ;
if ( step == l ) break ;
}
if ( step != l ) {
l = ( l - w[p.x][p.y][p.way] ) % (long long)( step - w[p.x][p.y][p.way] ) ;
repf( i , 1 , l ) {
move() ;
if (!flag ) i -- ;
}
}
while ( true ) {
move() ;
if ( flag ) break ;
}
printf("%d %d %c\n" , p.x , p.y , change(p.way) ) ;
}
int main(){
while ( scanf("%d %d %lld" , &n , &m , &l ) == 3 ) {
if ( n == 0 && m == 0 && l == 0 ) return 0 ;
l -- ;
clr(jl ) ; clr(w) ;
int sx , sy , way ;
repf( i , 1 , n )
scanf("%s" , s[i] + 1 ) ;
repf( i , 1 , n )
repf( j , 1 , m ) {
if ( s[i][j] != '.' && s[i][j] != '#' ) {
sx = i ; sy = j ; way = cal(s[i][j]) ;
}
}
bfs( sx , sy , way , 0 ) ;
}
}
Problem B: Butterfly(E)
/*
* Author: chlxyd
* Created Time: 2013/4/25 12:51:26
* File Name: B.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (lint i = 0; i < (n); ++i)
#define repf(i, a, b) for (lint i = (a); i <= (b); ++i)
#define repd(i, a, b) for (lint i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
const lint maxn = 100 + 10;
const lint maxmark = 1 << 16;
const lint maxint = 1LL << 60;
lint n, m[maxn], l[maxn];
lint times[maxn];
lint f[maxmark];
lint two(lint x) {
return 1 << x;
}
void init() {
rep (i, n) {
scanf("%lld%lld", &m[i], &l[i]);
lint mark = 0;
rep (j, m[i]) {
lint x, y;
scanf("%lld%lld", &x, &y);
x -= 6, y -= 7;
repf (k, x, y) {
if ((mark & two(k)) != 0)
l[i] = -maxint;
mark |= two(k);
}
}
times[i] = mark;
}
}
int main() {
while (scanf("%lld", &n) == 1) {
if (n == 0) break;
init();
memset(f, 0, sizeof(f));
lint ans = 0;
rep (i, n) {
repd (j, maxmark - 1, 0) {
if ((j & times[i]) == times[i]) {
f[j] = max(f[j], f[j - times[i]] + l[i]);
}
ans = max(ans, f[j]);
}
}
printf("%lld\n", ans);
}
return 0;
}
Problem C: ChineseClassics(N)
/*
* Author: chlxyd
* Created Time: 2013/4/25 15:38:56
* File Name: C.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
const int maxn = 10000 + 10;
int n;
map<string, int> mp;
vector<int> ans;
int v[maxn], ty[maxn], num[maxn], vis[maxn];
int maxId;
int getNum(string &str) {
int len = sz(str), h = len;
int res = 0;
rep (i, len) {
if ('0' <= str[i] && str[i] <= '9') {
res = res * 10 + str[i] - '0';
if (h == len) {
h = i;
}
}
}
str.resize(h);
return res;
}
void init() {
mp.clear();
memset(v, 0, sizeof(v));
memset(ty, -1, sizeof(ty));
memset(num, 0, sizeof(num));
mp["-"] = -1;
maxId = 0;
repf (i, 1, n) {
string str;
if (str == "-") continue;
cin >> str;
if (str[sz(str) - 1] == 'v') {
ty[i] = 0;
v[i] = 1;
str.resize(sz(str) - 1);
}
int tmp = getNum(str);
if (tmp == 0) continue;
//cout << str << endl;
num[i] = tmp;
if (mp.count(str) > 0) {
ty[i] = mp[str];
}
else {
mp[str] = ++maxId;
ty[i] = maxId;
}
}
//repf (i, 1, n) {
//printf("%d %d %d\n", v[i], ty[i], num[i]);
//}
}
bool mark(int w);
void stage3(int w, int nty, int step);
void dfs(int w);
void stage3(int w, int nty, int step) {
repd (i, w, 1) {
if (ty[i] == nty && num[i] == step && vis[i] == 0) {
if ( !mark(i) )
stage3(i - 1, nty, step + 1);
return;
}
}
}
bool mark(int w) {
if (vis[w] == 1) return false;
vis[w] = 1;
ans.push_back(w);
if (w > 1 && v[w - 1] == 1 && vis[w - 1] == 0) {
mark(w - 1);
return true;
}
else if (num[w] == 1) {
stage3(w - 1, ty[w], 2);
}
return false;
}
void dfs(int w) {
if (vis[w] == 1) dfs(w + 1);
if (w > n) return;
if (ty[w] == -1 && v[w] == 0) {
mark(w);
dfs(w + 1);
}
else if (v[w] == 1) {
dfs(w + 1);
}
else {
if (num[w] == 1) {
mark(w);
dfs(w + 1);
}
else dfs(w + 1);
}
}
void gao() {
ans.clear();
memset(vis, 0, sizeof(vis));
dfs(1);
rep (i, sz(ans))
printf("%d\n", ans[i]);
}
int main() {
while (scanf("%d", &n) == 1) {
if (n == 0) break;
init();
gao();
}
return 0;
}
Problem D: Revengeof Champernowne Constant(H)
一个母串,由所有的正整数拼接而成,123456789101112……给一个子串,问该串在母串中最早出现位置。
Solution
Tag:暴力
一道非常具有日本题风格的题目,比赛的时候开这道题真是太2了。。
思维还是很简单的,就是枚举匹配的长度,然后枚举从哪个位置开始匹配,然后每这么多位一枚举看是不是比前面的数大一就完了。
不过这个题细节实在是太多了,完全不适合我们做啊,被坑整场也没啥奇怪的。。。
说一些代表性的情况:1.中间某个数进位导致长度整体加1,如899100101。2.没有一个数是完整的,如99981999。3.开始的一部分全是9,得特判是否进位了,如9991000,9991100。4.前导零,如0010,0000(我一直觉得0000这种数据是不是太丧心病狂了点= =!)。具体还有很多很多情况,大家自己去摸索吧。
/*
* Author: chlxyd
* Created Time: 2013/4/25 19:26:38
* File Name: D.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (long long i = 0; i < (n); ++i)
#define repf(i, a, b) for (long long i = (a); i <= (b); ++i)
#define repd(i, a, b) for (long long i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
long long l , ret ;
char s[110] ;
long long num ( long long x ) {
long long have = 9 ;
long long i = 1 ;
long long ans = 0 ;
long long all = 9 ;
while ( x >= all ) {
ans += have * i ;
have *= 10 ;
all += have ;
i ++ ;
}
ans += ( x - (all-have) ) * i ;
return ans ;
}
long long pass1( long long a , long long b , long long lena , long long lenb , long long len , long long lena1 ) {
if ( b == 0 ) return false ;
if ( a == -1 || b == -1 ) return false ;
long long retr = b ;
repf( i , lena + lenb + 1 , len ) retr = retr * 10 ;
long long x = min( len - lenb , lena ) ;
long long c = 0 ;
long long ta = a + 1 ;
repf( i , 1 , x ) {
c = c * 10 + ta % 10 ;
ta /= 10 ;
}
repf( i , 1 , x ) retr = retr * 10 + c % 10 , c /= 10 ;
a ++ ;
repf( i , 1 , x ) a /= 10 ;
long long y = lena1 - x ;
repf( i , 1 , y ) {
if ( a % 10 != b % 10 ) return false ;
a /= 10 ; b /= 10 ;
}
return ret = num(retr-1)-lena1+1 ;
}
bool pass( long long a , long long b , long long type , long long len ) {
if ( b == 0 ) return false ;
if ( a == -1 || b == -1 ) return false ;
if ( type == 0 ) {
b -- ;
repf( i , 1 , len ) {
if ( b % 10 != a % 10 ) return false ;
b /= 10 ; a /= 10 ;
}
return true ;
}
else if ( type == 1 ) {
a ++ ;
string now = "" ;
while ( a ) {
now = now + (char)( a % 10 + '0' ) ;
a /= 10 ;
}
reverse(now.begin(),now.end()) ;
a = 0 ;
rep( j , len )
a = a * 10 + now[j] - '0' ;
repf( i , 1 , len ) {
if ( a % 10 != b % 10 ) return false ;
a /= 10 ; b /= 10 ;
}
return true ;
}
}
bool all( long long a , long long b , char c ) {
repf( i , a , b ) if ( s[i] != c ) return false;
return true ;
}
long long cal( long long a , long long b , long long sta ) {
long long ret = 0 ;
if ( s[a] == '0' && sta == 1 ) return -1 ;
repf( i , a , b )
ret = ret * 10 + s[i] - '0' ;
return ret;
}
bool calc( long long len , long long p ) {
long long i = p ;
long long last = - 1 ;
long long x ;
if ( l - p < len ) {
int add = 0 ;
if ( all( 0 , p - 1 , '9' ) ) add = 1 ;
long long a = cal( 0 , p - 1 , 0 ) , b = cal( p , l - 1 , 1 ) ;
return ret = pass1( a , b , p + add , l-p , len , p ) ;
}
while ( i + len <= l ) {
x = cal( i , i + len - 1 , 1 ) ;
if ( last != -1 ) {
if ( x != last + 1 ) return false ;
}
else {
if ( !pass( cal( 0 , i - 1 , 0 ) , x , 0 , i ) ) return false ;
}
long long tlen = len ;
if ( all( i , i + len - 1 , '9' ) ) len ++ ;
if ( last == -1 ) ret = num( x - 1 ) - p + 1 ;
last = x ;
i += tlen ;
}
if ( i <= l - 1 )
if ( !pass( x , cal( i , l - 1 , 1 ) , 1 , l - i ) ) return false ;
return true ;
}
int main(){
while ( scanf("%s" , s ) == 1 ) {
if ( s[0] == '#' ) return 0 ;
l = strlen(s) ;
if ( all( 0 , l - 1 , '0' ) ) {
long long now = 1 ;
repf( i , 1 , l ) now = now * 10 ;
printf("%lld\n" , num( now - 1 ) + 2 ) ;
continue;
}
long long now = -1 ;
calc(3,0);
repf( i , 1 , l ) {
bool ok = false ;
repf( j , 0 , i - 1 ) {
if ( i == l && j == 0 ) {
if ( s[0] == '0' ) continue ;
if ( now == -1 ) now = num(cal(0,l-1,0)-1)+1 ;
else
now = min( now , num(cal(0,l-1,0)-1)+1);
}
else if ( calc( i , j ) ) {
ok = true ;
if ( now == -1 ) now = ret ;
now = min( now , ret ) ;
}
}
if ( ok ) break ;
}
cout<<now<<endl;
}
}
Problem E: FullText Search(VH)
一个字符串,取所有长度为1和2的子串构成一个集合,问不包含这个字符串且长度为1和2的子串集合包含之前子串集合的字符串的最短长度(好绕口>.<)。
Solution
Tag:图论
把字母当成顶点,长度为2的子串转化为有向边,那么原问题转化为:求最短的路径长度,经过所有边一次,可以经过没有的边,且和初始方案不同。
显然长度<=2无解。
先不考虑和初始方案不同,假设可以相同。
如果原图变成了欧拉(回)路,那么答案显然就是欧拉(回)路的长度。
如果原图没有欧拉路,那么原图一定可以被拆分成很多链,我们将这些链连起来可以组成一条欧拉路。实际上,链的数量为,答案为链的数量加上边的数量。
如果不能和初始方案相同:
对于欧拉回路的情况,我们可以选择不同的起点来构造不同的方案。
对于很多链的情况,我们可以改变链的连接顺序来构造不同的方案。
对于欧拉通路的情况,开始想了很多结论,发现都是错的,下面给出正确判法。
添加一条从终点到起点的边,那么欧拉通路是否唯一等价于当前欧拉回路是否唯一。
对于欧拉回路:
1. 如果存在一个点的出度大于2,那么不唯一。
2. 对于出度为2的点,他的2个出度会延展出两颗搜索树,如果两棵树之间有交集,那么不唯一。
3. 不满足上述两条情况则唯一。
对于欧拉通路方案唯一的情况,我们加一个长度显然可以构造出和原方案不一样的解,具体见代码。
/*
* Author: chlxyd
* Created Time: 2013/4/27 12:11:17
* File Name: E.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
char s[2000] ;
int e[300][300] ;
bool bj[300] ;
int out[300], in[300] ;
set<int> st[3];
void dfs( int root , int i , int flag ) {
if ( i == root ) return ;
if ( st[flag].find(i) != st[flag].end() ) return ;
st[flag].insert(i) ;
repf( j , 1 , 256 )
if ( e[i][j] )
dfs( root , j , flag ) ;
}
bool disjoint() {
for ( set<int>::iterator x = st[1].begin() ; x != st[1].end() ; x ++ ) {
if ( st[2].find(*x) != st[2].end() ) return true ;
}
return false ;
}
int solve() {
if ( strlen(s) <= 2 ) return -1 ;
rep( i , strlen(s) )
bj[s[i]] = true ;
rep( i , strlen(s) - 1 ) {
if ( !e[s[i]][s[i+1]] ) {
e[s[i]][s[i+1]] = true ;
out[s[i]] ++ ; in[s[i+1]] ++ ;
}
}
int ans = 0 ;
repf( i , 1 , 256 )
if ( bj[i] )
ans = ans + max( 0 , out[i] - in[i] ) ;
int enumb = 0 ;
repf( i , 1 , 256 )
repf( j , 1 , 256 )
enumb += e[i][j] ;
if ( ans == 0 )
return enumb + 1 ;
else if ( ans == 1 ) {
int ss , tt ;
repf( i , 1 , 256 ) if ( out[i] - in[i] == 1 ) ss = i ;
repf( i , 1 , 256 ) if ( in[i] - out[i] == 1 ) tt = i ;
e[tt][ss] = true ;
out[tt] ++ ; in[ss] ++ ;
if ( enumb + 1 < strlen(s) ) return enumb + 1 ;
repf( i , 1 , 256 ) {
if ( out[i] > 2 ) return enumb + 1 ;
}
repf( i , 1 , 256 ) {
if ( out[i] == 2 ) {
int top = 0 ;
st[1].clear() ; st[2].clear() ;
repf( j , 1 , 256 )
if ( e[i][j] )
dfs(i,j,++top) ;
//cout<<"dis"<<i<<endl;
if ( disjoint() ) return enumb + 1 ;
}
}
return enumb + 2 ;
}
else
return enumb + ans ;
}
int main(){
//freopen("E.out","w",stdout);
int ca = 0 ;
while ( scanf("%s" , s ) == 1 ) {
clr(in) ; clr(out) ; clr(e) ; clr(bj) ;
if ( s[0] == '#' ) return 0 ;
int now = solve() ;
ca ++ ;
if ( now == -1 ) puts("No Results") ;
else printf("%d\n" , now ) ;
}
}
Problem F: MysteriousMaze(N)
/*
* Author: xioumu
* Created Time: 2013/4/26 13:41:20
* File Name: F.cpp
* solve: F.cpp
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clr(x) memset(x,0,sizeof(x))
#define clrs( x , y ) memset(x,y,sizeof(x))
#define out(x) printf(#x" %d\n", x)
#define sqr(x) ((x) * (x))
typedef long long lint;
const int maxint = -1u>>1;
const double eps = 1e-8;
const int maxn = 1000 + 3;
const int maxnum = 1000 * 1000 * 4 + 3;
int sgn(const double &x) { return (x > eps) - (x < -eps); }
char op[maxnum];
char squ[maxn][maxn];
int dir[maxnum], dis[maxnum], next[maxnum][10], v[maxnum];
int sx, sy, ex, ey;
int n, m, pn;
queue<int> que;
int bx[] = {-1, 0, 1, 0};
int by[] = {0, 1, 0, -1};
void init() {
scanf("%s", op + 1);
rep (i, n) {
scanf("%s", squ[i]);
rep (j, m) {
if (squ[i][j] == 'S')
sx = i, sy = j;
if (squ[i][j] == 'G')
ex = i, ey = j;
}
}
int now = 0;
dir[0] = 0;
rep (i, pn) {
if (op[i + 1] == 'L')
now -= 1;
else now += 1;
now = (now + 4) % 4;
dir[i + 1] = now;
}
//printf("%d %d\n", ex, ey);
//rep (i, pn + 1) {
//printf("%d ", dir[i]);
//}
//printf("\n");
int last[10];
last[0] = last[1] = last[2] = last[3] = pn + 1;
repd (i, pn, 0) {
last[dir[i]] = i;
rep (j, 4)
next[i][j] = last[j];
}
//rep (i, pn + 1) {
//rep (j, 4)
//printf("%d ", next[i][j]);
//printf("\n");
//}
}
bool ok(int x, int y) {
return 0 <= x && x < n && 0 <= y && y < m;
}
int getid(int x, int y, int d) {
return x * 1000 * 4 + y * 4 + d;
}
void getMark(int mark, int &x, int &y, int &d) {
x = mark / (1000 * 4);
mark %= 1000 * 4;
y = mark / 4;
mark %= 4;
d = mark;
}
bool gao() {
while (!que.empty()) que.pop();
repf (i, 0, getid(n - 1, m - 1, 3)) {
dis[i] = maxint;
v[i] = 0;
}
int tmp = getid(sx, sy, 0);
dis[tmp] = 0;
que.push(tmp);
while (!que.empty()) {
int x, y, d, nid, len;
nid = que.front();
que.pop();
v[nid] = 0;
getMark(nid, x, y, d);
len = dis[nid];
//printf("%d %d %d %d\n", x, y, d, len);
if (x == ex && y == ey) return true;
rep (i, 4) {
if (next[len][i] <= pn) {
int cid = getid(x, y, i);
if (dis[cid] > next[len][i]) {
dis[cid] = next[len][i];
if (v[cid] == 0) {
v[cid] = 1;
que.push(cid);
}
}
}
}
int nx = x + bx[d];
int ny = y + by[d];
if (ok(nx, ny) && squ[nx][ny] != '#') {
int cid = getid(nx, ny, d);
if (dis[cid] > len) {
dis[cid] = len;
if (v[cid] == 0) {
v[cid] = 1;
que.push(cid);
}
}
}
}
return false;
}
int main() {
while (scanf("%d%d%d", &n, &m, &pn) == 3) {
if (n == 0 && m == 0 && pn == 0) break;
init();
bool ans = gao();
if (ans) printf("Yes\n");
else printf("No\n");
}
return 0;
}
Problem G: NumberSorting(E)
给一个10W个数的连续自然数区间,问区间内有多少不同的数的集合,他们的字典序顺序和大小顺序一样。
Solution
Tag:数据结构
把数按照字典序排序,然后建一颗线段树,维护第i个数结尾的顺序和字典序相同的集合有多少个,从大到小扫描每一个数,以这个数结尾的序列集合数量等于在线段树中他对应的节点之前的所有点结尾的数量总和,然后插入到线段树中。最后所有点结尾的序列总和就是答案。
/*
* Author: chlxyd
* Created Time: 2013/4/25 14:03:35
* File Name: G.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((long long )(v).size())
#define rep(i, n) for (long long i = 0; i < (n); ++i)
#define repf(i, a, b) for (long long i = (a); i <= (b); ++i)
#define repd(i, a, b) for (long long i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
struct treetype {
long long l , r, sum ;
}tree[410000] ;
long long n , mod ;
long long x[110000], z[110000] ;
string y[110000] ;
map<long long ,long long > mp ;
string cal( long long x ) {
string ret ; ret.clear() ;
while ( x ) {
ret += (char)('0' + x % 10 );
x /= 10 ;
}
reverse(ret.begin(), ret.end());
return ret ;
}
long long cal1( long long x ) {
long long ret = 0 ;
rep( i , y[x].size() )
ret = ret * 10 + y[x][i] - '0' ;
//cout<<y[x]<<" "<<ret<<endl;
return ret ;
}
void insert( long long i , long long x , long long c ) {
tree[i].sum += c ; tree[i].sum %= mod ;
if ( tree[i].l == tree[i].r ) return ;
long long mid = ( tree[i].l + tree[i].r ) / 2 ;
if ( x <= mid ) insert( i * 2 , x , c ) ;
else insert( i * 2 + 1 , x , c ) ;
}
long long sum( long long i , long long l , long long r ) {
//cout<<i<<" "<<l<<" "<<r<<endl;
if ( l > r ) return 0 ;
if ( tree[i].l == l && tree[i].r == r ) return tree[i].sum ;
long long mid = ( tree[i].l + tree[i].r ) / 2 ;
if ( r <= mid ) return sum( i * 2 , l , r ) ;
else if ( l > mid ) return sum( i * 2 + 1 , l , r ) ;
else return (sum( i * 2 , l , mid ) + sum( i * 2 + 1 , mid + 1 , r )) % mod ;
}
void maketree( long long i , long long l , long long r ) {
tree[i].l = l ; tree[i].r = r ; tree[i].sum = 0 ;
if ( l == r ) return ;
long long mid = ( l + r ) / 2 ;
maketree( i*2 , l , mid ) ;
maketree( i*2+1 , mid + 1 , r ) ;
}
int main(){
long long a , b ;
while ( scanf("%lld %lld %lld" , &a , &b , &mod ) == 3 ) {
if ( a == 0 && b == 0 && mod == 0 ) return 0 ;
mp.clear();
long long ans = 0 ;
n = b - a + 1 ;
repf( i , 1 , b - a + 1 ) x[i] = a + i - 1 ;
repf( i , 1 , b - a + 1 ) y[i] = cal( a + i - 1 ) ;
sort( x + 1 , x + n + 1 ) ;
sort( y + 1 , y + n + 1 ) ;
repf( i , 1 , n )
z[i] = cal1( i ) ;
repf( i , 1 , n ) {
mp[z[i]] = i ;
}
maketree( 1 , 1 , n ) ;
repf( i , 1 , n ) {
long long now = 1 + sum( 1 , 1 , mp[x[i]] - 1 ) ;
ans += now ;
insert( 1 , mp[x[i]] , now ) ;
ans %= mod ;
}
printf("%lld\n" , ans ) ;
}
}
Problem H: (unknown)
Problem I: MobileNetwork(N)
比赛的时候居然没敢写。。拙计。
给一个网络,每条边的流量是一个多项式,问起点到终点的最大流量。
Solution
Tag:网络流
一个裸地最大流模板。。然后自己定义一个多项式的数据结构,支持比较大小,加减,输出操作就行了,水题。
/*
* Author: chlxyd
* Created Time: 2013/4/26 21:45:30
* File Name: I.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define clr(x) memset( x , 0 , sizeof(x) )
#define sz(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define clrs( x , y ) memset( x , y , sizeof(x) )
int n,m;
int dui[100000];
int d[60];//保存节点level
bool bj[60];
struct dxs {
int a[52] ;
int len ;
void clear() {
clr(a) ; len = 0 ;
}
void make( string s ) {
clr(a) ;
s = s + '+' ; len = 0 ;
int num = 0 , b = 0 , sta = 0 ;
rep( i , s.size() ) {
if ( s[i] >= '0' && s[i] <= '9') {
if ( sta == 0 ) num = num * 10 + s[i] - '0' ;
else if ( sta == 2 ) b = b * 10 + s[i] - '0' ;
}
else if ( s[i] == 'x' ) sta = 1 ;
else if ( s[i] == '^' ) sta = 2 ;
else if ( s[i] == '+' ) {
//cout<<num<<" "<<b<<endl;
if ( num == 0 ) num = 1 ;
if ( sta == 1 ) b = 1 ;
a[b] += num ;
len = max( len , b ) ;
num = b = 0 ;
sta = 0 ;
}
}
}
bool operator < ( const dxs & q ) const {
if ( len != q.len ) return len < q.len ;
repd( i , len , 0 ) {
if ( a[i] != q.a[i] )
return a[i] < q.a[i] ;
}
return false;
}
bool zero() {
return (len == 0 && a[0] == 0 ) ;
}
dxs operator + ( const dxs & q ) const {
dxs now ; now.clear() ;
now.len = max( len , q.len ) ;
repf( i , 0 , now.len ) now.a[i] = a[i] + q.a[i] ;
return now ;
}
dxs operator - ( const dxs & q ) const {
dxs now ; now.clear() ;
now.len = max( len , q.len ) ;
repf( i , 0 , now.len ) now.a[i] = a[i] - q.a[i] ;
int tmp = now.len ;
repd( i , tmp , 0 ) {
if ( now.a[i] == 0 ) now.len -- ;
else break ;
}
if ( now.len == -1 ) now.len = 0 ;
return now ;
}
void show() {
bool first = true ;
if ( len == 0 && a[0] == 0 ) {
printf("0\n") ;
return ;
}
repd( i , len , 0 ) {
if ( a[i] != 0 ) {
if ( !first ) printf("+") ;
if ( i == 0 ) printf("%d" , a[i] ) ;
else if ( a[i] != 1 ) printf("%d" , a[i] ) ;
if ( i != 0 ) printf("x") ;
if ( i > 1 ) printf("^%d",i);
}
first = false ;
}
cout<<endl;
}
}e[60][60],ans;
dxs dfs(int t, dxs v){//dfs找连续增广路径
if (t==n || v.zero() ) return v;
dxs flow , ans ; ans.clear() ;
for (int i=1;i<=n;i++){
if (!e[t][i].zero() && d[i]==d[t]+1){
flow=dfs(i,min(v,e[t][i]));//递归得到下面的可改进量
e[t][i] = e[t][i] - flow; e[i][t] = e[i][t] + flow;//修改该边流量
v = v - flow; ans = ans + flow;//修改阈值 更新流量
if (v.zero()) break;
}
}
return ans;
}
bool bfs(int s){//bfs标号过程 若终点未被标号则表示无可增广路径
int head,last,x;
memset(d,0,sizeof(d));
memset(bj,false,sizeof(bj));//bj表示节点是否被标号
d[s]=1;head=0;last=1;dui[last]=s;bj[s]=true;//源点入队
while (head<last){
x=dui[++head];
for (int i=1;i<=n;i++){//枚举所有邻接节点
if (!bj[i] && !e[x][i].zero() ){//该边有意义
bj[i]=true;
d[i]=d[x]+1;
dui[++last]=i;
}
}
}
return bj[n];
}
void clrr(){
ans.clear() ;
}
void makegraph(){
int a,b;
string c ;
repf( i , 1 , n )
repf( j , 1 , n )
e[i][j].clear() ;
for (int i=1;i<=m;i++){
scanf("%d %d",&a,&b);
cin>>c ;
e[a][b].make(c);
e[b][a].make(c);
}
}
int main(){
while ( scanf("%d %d" , &n , &m ) == 2 ) {
if ( n == 0 && m == 0 ) return 0 ;
clrr();
makegraph();
dxs INF ; INF.clear() ;
INF.len = 51 ; INF.a[51] = 1 ;
while (bfs(1))
ans = ans + dfs(1,INF);
ans.show() ;
}
}
Problem J: (unknown)
UPD:这套没有更新了。。就这样吧。。