A。题目:http://acm.timus.ru/problem.aspx?space=1&num=2024

题意:求一个包含K个不同字符的集合的最大长度,还有组成这个长度的集合的个数

做法:因为求的集合,不需连续 ,直接统计各个字符的出现次数 。

那么答案一就是按出现次数排序再加前K个。

答案二只与K个中集合大小最小的分配相关。

/* hl */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
char s[];
ll c[][]; ll calc(int n, int m) {
ll res = ;
for(int i=; i<=m; i++) {
res *= n-i+;
res /= i;
}
return res;
} void c_init() {
for(int i=; i<=; i++)
for(int j=; j<=; j++)
c[i][j] = calc(i, j);
} struct node {
ll cnt ; int vis ;
bool operator <( const node &a ) const{
if( vis!=a.vis ) return vis >a.vis ;
else return cnt > a.cnt ;
}
}e[]; void init() {
for( int i = ; i < ; ++i ) e[i].cnt = e[i].vis = ;
} int main()
{
#ifdef LOCAL
freopen("in","r",stdin);
#endif
c_init();
int k ;
while( ~scanf("%s%d",s,&k) ) {
int len = strlen(s);
init();
for( int i = ; i < len ; ++i ) {
e[ s[i] - 'a' ].cnt ++ ;
e[ s[i] - 'a' ].vis = ;
}
sort( e , e + ) ;
ll ans1 = , ans2 = , last = - ;
int tmp = ;
for( int i = ; i < k && e[i].vis ; ++i ) {
ans1 += e[i].cnt;
if( e[i].cnt == last ) tmp++ ;
else {
last = e[i].cnt ; tmp = ;
}
}
int all = ;
for( int i = ; i < && e[i].vis ; ++i ) {
if( e[i].cnt == last ) all++ ;
}
ans2 = c[all][tmp];
printf("%I64d %I64d\n",ans1,ans2);
}
return ;
}

B. 题目 : http://acm.timus.ru/problem.aspx?space=1&num=2025

题意 : n 个人分到 k 个组 ,不同组的人可以打架 , 求打架次数最多是多少

平均分配后 , 处理一个前缀/后缀和,然后一个个组统计

/*  hl  */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = ;
int x[N] , sum[N] ;
int main()
{
#ifdef LOCAL
freopen("in","r",stdin);
#endif
int _ , n , m ;
scanf("%d", &_);
while(_--) {
scanf("%d%d",&n,&m);
for( int i = ; i <= m ; ++i ) {
x[i] = n / m ;
}
int c = n % m ;
for( int i = ; i <= m && i <= c ; ++i ) {
x[i]++ ;
}
sum[m] = x[m] ;
for( int i = m - ; i >= ; --i ) sum[i] = sum[i+] + x[i] ;
int ans = ;
for( int i = ; i < m ; ++i ) {
ans += x[i] * sum[i+] ;
}
printf("%d\n",ans);
}
return ;
}

C. 题目: http://acm.timus.ru/problem.aspx?space=1&num=2026

题意 : n 节课 .. 不同字母不同课 , ‘?’代表未确定 ,

奇位置加字符权,偶位置减字符权 , 问至少安排k节不同的课能够得到的最大权

若然,已经够k个不同字符就直接贪心放

    不然,先统计奇偶位置的问号 , 再看看应该在奇问号,还是在偶问号处放新字符。

这就要选跟最优字符的距离较小的那个新字符了

放够了剩下的就贪心

/* hl */
#include <bits/stdc++.h>
using namespace std ;
string s ;
int k ;
bool vis[] ;
queue<int> o , e ; int Run() { while( cin >> s >> k ) {
memset( vis , false , sizeof vis ) ;
int c = , cnt1 = , cnt2 = ;
for( int i = ; i < s.length() ; ++i ) {
if( s[i] == '?') {
if( i& ) cnt2++ ;
else cnt1++ ;
}
else if( !vis [ s[i] - 'a' ] ) {
vis[ s[i] - 'a' ] = true , c++ ;
}
}
//cout << cnt1 << ' ' << cnt2<< ' ' << c << endl ;
if( cnt1 + cnt2 + c < k ) {
cout << "-1" << endl ; continue ;
}
for( int i = c ; i < k ; ++i ) {
int c1 = - , c2 = ;
for( int j = ; j >= ; --j ) if( !vis[j] ) { c1 = j ; break ; }
for( int j = ; j < ; ++j ) if( !vis[j] ) { c2 = j ; break ; }
if( - c1 <= c2 && cnt1 ) {
cnt1-- ;
vis[c1] = true ;
o.push(c1);
} else {
vis[c2] = true ;
e.push(c2);
}
}
for( int i = ; i < s.length() ; ++i ) {
if( s[i] == '?' ) {
if( i& ) { // even position
if( !e.empty() ) { s[i] = e.front() + 'a' ; e.pop() ; }
else s[i] = 'a' ;
} else {
if( !o.empty() ) { s[i] = o.front() + 'a' ; o.pop() ; }
else s[i] = 'z' ;
}
}
}
cout << s << endl ;
}
return ;
}
int main() {
// freopen("in.txt","r",stdin);
ios::sync_with_stdio() ;
return Run();
}
D :http://acm.timus.ru/problem.aspx?space=1&num=2027
模拟题
blue :
用一个数组保存整个程序
用一个pii的指针保存指针的位置
用一个27位的数组保存寄存器
剩下就是模拟了,注意异常的处理
其实我写的复杂,写烂了。。后来想想应该是十几分钟写完的代码
 
/* blue */
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(i=(l); i<(r); i++)
#define drep(i, l, r) for(int i=(l); i<(r); i++)
typedef long long ll;
typedef pair<int,int> pii;
const int N = ; // Exception define
#define OE 0
#define RE 1
#define TLE 2
#define OK 3
char EXCEPTION[][] = {"OVERFLOW ERROR","RUNTIME ERROR","TIME LIMIT EXCEEDED"}; // global
int n,m;
char program[N][N]; // input stream system
int read_pos, read_cnt, read_num[];
void read_init() {
read_pos = ;
scanf("%d", &read_cnt);
for(int i=; i<read_cnt; i++) scanf("%d", read_num+i);
}
int read_next() {
if(read_pos >= read_cnt) return read_num[read_cnt-];
return read_num[read_pos++];
} // pointer system
pii pointer;
#define xx first
#define yy second
int dir;
const int dx[] = {,,,-};
const int dy[] = {,,-,};
inline bool inside(const int &x, const int &y) {return x>=&&x<n && y>=&&y<m;}
int move() {
pointer.xx += dx[dir];
pointer.yy += dy[dir];
if(!inside(pointer.xx, pointer.yy)) return RE;
return OK;
}
void changedir(char c) {
if(c=='>') dir = ;
else if(c=='v') dir = ;
else if(c=='<') dir = ;
else dir = ;
} // REG system
int reg[];
#define CURREG reg[26]
void swap_reg(char c) {
int t = reg[c-'A'];
reg[c-'A'] = CURREG;
CURREG = t;
} // INC and DEC
int INC() {
CURREG++;
if(CURREG > || CURREG < -) return OE;
return OK;
}
int DEC() {
CURREG--;
if(CURREG > || CURREG < -) return OE;
return OK;
} // At @
void At() {
if(CURREG==) dir--;
else dir++;
if(dir<) dir=;
if(dir>) dir=;
} // choose command system
#define CMD program[pointer.xx][pointer.yy]
inline bool isDir() {return CMD=='v' || CMD=='^' || CMD=='<' || CMD=='>';}
inline bool isREG() {return CMD>='A' && CMD<='Z';}
inline bool isRead() {return CMD=='?';}
inline bool isWrite() {return CMD=='!';}
inline bool isINC() {return CMD=='+';}
inline bool isDEC() {return CMD=='-';}
inline bool isAt() {return CMD=='@';}
inline bool isTerminal() {return CMD=='#';} int main()
{
#ifdef LOCAL
freopen("in","r",stdin);
#endif
while(scanf("%d%d", &n, &m)!=EOF) {
memset(reg, , sizeof(reg));
// read program
for(int i=; i<n; i++) scanf("%s", program[i]);
// input stream
read_init();
// pointer
pointer = pii(, ); dir = ;
int cnt = ;
while(true) { cnt++;
if(cnt>) {
puts(EXCEPTION[TLE]);
break;
} int status = OK; if(isDir()) changedir(CMD);
else if(isREG()) swap_reg(CMD);
else if(isRead()) CURREG = read_next();
else if(isWrite()) {printf("%d\n", CURREG);CURREG=;}
else if(isINC()) status = INC();
else if(isDEC()) status = DEC();
else if(isAt()) At();
else if(isTerminal()) break;
if(status != OK) {
puts(EXCEPTION[status]);
break;
} if(status != OK) {
puts(EXCEPTION[status]);
break;
} status = move();
if(status != OK) {
puts(EXCEPTION[status]);
break;
}
}
}
return ;
}

赛后我自己也写了一次。

注意下 TLE 的判断 要符合这句话 :

If the termination operator is not executed during 106 steps and none of the above two errors occurs, then the program terminates with TIME LIMIT EXCEEDED.

然后还要注意得先判 OVE 再判 RE. ,这里我wa了好几发才发现

/* hl */
#include <bits/stdc++.h>
using namespace std ;
const int N = ;
const int TLE = ;
#define OVE 100000
int h , w ;
string mp[N] ;
int dx[] = { , , , - } ;
int dy[] = { , , - , } ;
int x , y , dir , tim ;
int scan[] , reg[] ; int Run() {
while( cin >> h >> w ) {
for( int i = ; i < h ; ++i ) cin >> mp[i] ;
int n ; cin >> n ;
for( int i = ; i < n ; ++i ) cin >> scan[i] ;
dir = x = y = tim = ;
int c = , cur = ;
bool finish = false ;
memset( reg , , sizeof reg ) ;
while( true ) {
tim++ ;
switch( mp[x][y] ) {
case '>' : dir = ; break ;
case 'v' : dir = ; break ;
case '<' : dir = ; break ;
case '^' : dir = ; break ;
case '.' : break;
case '?' : cur = scan[c>=n?n-:c] ; c++; break ;
case '!' : cout<<cur<<endl ; cur = ; break ;
case '+' : cur++ ; break ;
case '-' : cur-- ; break ;
case '@' : dir = ( cur ? ( dir + ) % : ( dir + ) % ) ; break ;
case '#' : finish = true ; break ;
default : swap( cur , reg[ mp[x][y] - 'A' ] ) ; break;
}
if( finish ) break ;
x += dx[dir] ; y += dy[dir] ;
if( cur > OVE || cur < -OVE ) {
cout << "OVERFLOW ERROR" << endl;
break ;
} else if( x < || x >= h || y < || y >= w ) {
cout << "RUNTIME ERROR" << endl;
break ;
} else if( tim == TLE ) {
cout << "TIME LIMIT EXCEEDED" << endl;
break ;
}
}
}
return ;
}
int main() {
// freopen("in.txt","r",stdin);
ios::sync_with_stdio() ;
return Run();
}

E:http://acm.timus.ru/problem.aspx?space=1&num=2028

题目要求.. 弄一个输入,然后再输入 1 n ,放到D题能够跑出前 n 项和 。

做法: 根据D题,数字每次操作只能够+1 ,还有交换操作当前寄存器和内存寄存器的值 , 一个判断操作@ ,能够判当前寄存器是否为 0 。

当前寄存器用reg表示, 其余寄存器 A~Z吧

如何把一个数n弄成两个呢? 直接把这个数放到reg上,每次-1,就换出A来+1 , 换出B+1 。

用@判出reg值为0 的时候, A , B 就有n了

然后再用一个C来保存结果 。 A 复制成两个后 , 把B也像上述操作一样加到C上 , 直到B为0 。

A不等于0 ? A的值 -1  , 复制到B上 ,进行操作1 。

A 等于0 ? 输出C 。

然后画一下图, 按照D题题意换成字符就OK了 。

/* hl */
#include <bits/stdc++.h>
using namespace std ;
int h , w ;
string s[] = {
"?......A.>..v..........<",
"...............>C.!#....",
".v..........@>A@........",
"...............>.>....v.",
"..............>..^......",
"..............@-B+BA+A<.",
"..............>..A-AB..^",
".>C+C-...^.............."
}; int Run() {
cout << << ' ' << << endl ;
for( int i = ; i < ; ++i ) cout << s[i] << endl ;
return ;
}
int main() {
// freopen("in.txt","r",stdin);
ios::sync_with_stdio() ;
return Run();
}

F: http://acm.timus.ru/problem.aspx?space=1&num=2029

汉诺塔变形吧。 题意就是把一个全部放在A汉诺塔 移成 给出的状态

可以发现所有状态都是可以得到的,只要你合法地移动

要明白 , 移动第i个到目标位置 。

如果第i个已经在目标位置的话,可以直接忽略它了。然后去处理第 i - 1 个 。

        如果不在目标位置,要把第 i 个移动到目标位置 ,必须把上面的 i -1 个移动到 除 原位置 和 目标位置 的那个位置上 , 需要 2^( i-1)-1 步 。

加上自己移动的那一步就是 2^( i-1)  因为移动的位置唯一,这里是无可避免的 , 必须加到答案上 。

/* hl */
#include <bits/stdc++.h>
using namespace std ;
typedef long long LL;
int n ;
string s ;
LL ans ;
void dfs( int dep , int pos ) {
if( dep < ) return ;
int goal = s[dep] - 'A' ;
// cout << dep << ' ' << pos << ' ' << ans << endl ;
if( goal == pos ) dfs( dep - , pos ) ;
else {
ans += (1LL<<dep) ;
if( pos == ) {
if( goal == ) dfs( dep - , ) ;
else dfs( dep - , ) ;
} else if( pos == ) {
if( goal == ) dfs( dep - , ) ;
else dfs( dep - , ) ;
} else {
if( goal == ) dfs( dep - , ) ;
else dfs( dep - , ) ;
}
}
}
int Run() {
while( cin >> n >> s ) {
ans = ;
dfs( s.length() - , ) ;
cout << ans << endl ;
}
return ;
}
int main() {
// freopen("in.txt","r",stdin);
ios::sync_with_stdio() ;
return Run();
}

G: http://acm.timus.ru/problem.aspx?space=1&num=2030

有3种做法:

O( n + m ) :  转成有根树 , 在线更新父亲,离线更新儿子 。

更新的时候就是 父亲的离线值 + 自身的在线值 。

然后按照上面讲的来更新

/*  VM  */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define rep1(i, n) for(int i = 1; i <= (n); ++i)
#define For(i, b, e, s) for(int i = (b); i != (e); i += (s))
const int N = ;
const int mod = ;
vector<int> G[N];
int par[N], val[N], add[N], n; void dfs(int u, int p){
par[u] = p;
for(unsigned int i = ; i < G[u].size(); ++i) if(G[u][i] != p) dfs(G[u][i], u);
} int main(){
int u, v, m;
while(scanf("%d", &n) == ){
rep(i, n + ) G[i].clear();
memset(add, , sizeof(add[]) * (n + ));
rep1(i, n) scanf("%d", &val[i]);
rep(i, n - ){
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(, );
scanf("%d", &m);
while(m--){
scanf("%d%d", &u, &v);
if(u == ){
int t = val[v] + add[par[v]];
if(t >= mod) t-= mod;
if((val[par[v]] += t) >= mod) val[par[v]] -= mod;
if((add[v] += t) >= mod) add[v] -= mod;
}
else{
int t = val[v] + add[par[v]];
if(t >= mod) t-= mod;
printf("%d\n", t);
}
}
}
return ;
}

O( n logn )

转成有根树 ,再bfs一次把树给分成一层层 , 同一个父亲的结点编号要连续 。

然后就是用一个能够区间 logn 操作的数据结构进行 单点查询,对父亲单点更新, 对孩子成段更新 。

/* hl */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define X first
#define Y second
const int N = ;
const int mod = 1e9+; int n , fa[N] , cnt , idx[N] , l_s[N] , r_s[N] , x[N] ;
vector<int>g[N]; void bfs() {
int cnt = ;
memset( l_s , 0x3f , sizeof l_s );
memset( r_s , - , sizeof r_s );
queue<pii>que;
que.push( pii(,) ) ;
while( !que.empty() ) {
int u = que.front().X , pre = que.front().Y ;
que.pop();
fa[u] = pre ;
idx[u] = cnt++ ;
l_s[pre] = min( l_s[pre] , idx[u] );
r_s[pre] = max( r_s[pre] , idx[u] );
for( int i = ; i < g[u].size() ; ++i ) {
int v = g[u][i] ;
if( pre == v ) continue ;
que.push( pii( v,u ) ) ;
}
}
} ll c[N];
void init() {
memset( c , , sizeof c );
}
int lowbit( int x ) {
return x&-x;
} void update( int pos , ll key ) {
while( pos < n + ) {
c[pos] = ( c[pos] + key + mod ) % mod ;
pos += lowbit(pos);
}
} ll query( int pos ) {
ll res = ;
if( !pos ) return ;
while( pos > ) {
res = ( res + c[pos] ) % mod ;
pos -= lowbit(pos);
}
return res ;
} int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
while( ~scanf("%d",&n) ) { for( int i = ; i <= n ; ++i ) scanf("%d",&x[i]);
for( int i = ; i <= n ; ++i ) g[i].clear(); for( int i = ; i < n ; ++i ) {
int u , v ; scanf("%d%d",&u,&v);
g[u].push_back(v); g[v].push_back(u);
} bfs(); init();
for( int i = ; i <= n ; ++i ) {
update( idx[i] , x[i] );
update( idx[i] + , -x[i] );
} int m ;
scanf("%d",&m);
while( m -- ) {
int op , c ;
scanf("%d%d",&op,&c);
if( op == ) {
ll v = query( idx[c] ) ;
if( c != ) {
update( idx[ fa[c] ] , v ) ;
update( idx[ fa[c] ] + , -v ) ;
}
if( r_s[c] != - ) {
update( l_s[c] , v ) ;
update( r_s[c] + , -v ) ;
}
} else {
printf("%I64d\n",query( idx[c] ));
}
}
}
return ;
}

树分层+树状数组

用树状数组要注意一点就是 差分的时候有减操作 , 取模后有负数出现 , (x % mod + mod ) % mod 就可以解决了 。

线段树的话可以避免上面的差错 , 不过不知道训练中何解WA , 重新写过一次然后就过了

/* hl */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define X first
#define Y second
const int N = ;
const int mod = 1e9+;
#define root 1,n+20,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define lr rt<<1
#define rr rt<<1|1 int n , fa[N] , cnt , idx[N] , l_s[N] , r_s[N] ;
ll x[N] ;
vector<int>g[N]; ll date[N<<] , lazy[N<<] ; void build( int l , int r , int rt ){
date[rt] = lazy[rt] = ;
if( l == r ) return ;
int mid = (l+r)>>;
build(lson) , build(rson) ;
} void Down( int rt ) {
if( lazy[rt] ) {
date[lr] = ( date[lr] + lazy[rt] ) % mod ;
date[rr] = ( date[rr] + lazy[rt] ) % mod ;
lazy[lr] = ( lazy[lr] + lazy[rt] ) % mod ;
lazy[rr] = ( lazy[rr] + lazy[rt] ) % mod ;
lazy[rt] = ;
}
} void update( int l , int r , int rt , int L , int R , ll v ) {
if( l == L && r == R ) {
date[rt] = ( date[rt] + v ) % mod ;
lazy[rt] = ( lazy[rt] + v ) % mod ;
return ;
}
Down( rt ) ;
int mid = (l+r)>>;
if( R <= mid ) update( lson , L , R , v ) ;
else if( L > mid ) update( rson , L , R , v ) ;
else update( lson , L , mid , v ) , update( rson , mid + , R , v ) ; } ll query( int l , int r , int rt , int x ) {
if( l == r ) {
return date[rt] ;
}
Down( rt ) ;
int mid = (l+r)>>;
if( x <= mid ) return query( lson , x ) ;
else return query( rson , x );
} void bfs() {
int cnt = ;
memset( l_s , 0x3f , sizeof l_s );
memset( r_s , - , sizeof r_s );
queue<pii>que;
que.push( pii(,) ) ;
while( !que.empty() ) {
int u = que.front().X , pre = que.front().Y ;
que.pop();
fa[u] = pre ;
idx[u] = cnt++ ;
l_s[pre] = min( l_s[pre] , idx[u] );
r_s[pre] = max( r_s[pre] , idx[u] );
for( int i = ; i < g[u].size() ; ++i ) {
int v = g[u][i] ;
if( pre == v ) continue ;
que.push( pii( v,u ) ) ;
}
}
} int main()
{
ios::sync_with_stdio() ;
while( cin >> n ) { for( int i = ; i <= n ; ++i ) cin >> x[i] ;
for( int i = ; i <= n ; ++i ) g[i].clear(); for( int i = ; i < n ; ++i ) {
int u , v ; cin >> u >> v ;
g[u].push_back(v); g[v].push_back(u);
} bfs();
build(root);
for( int i = ; i <= n ; ++i )
update( root , idx[i] , idx[i] , x[i] );
int m ; cin >> m ;
while( m -- ) {
int op , c ; cin >> op >> c ;
if( op == ) {
ll v = query( root , idx[c] ) ;
if( c != ) {
update( root , idx[ fa[c] ] , idx[ fa[c] ] , v ) ;
}
if( r_s[c] != - ) {
update( root , l_s[c] , r_s[c] , v ) ;
}
} else {
cout << query( root , idx[c] ) << endl ;;
}
}
}
return ;
}

线段树

O( n sqrt(n) )

把结点分层两类, 孩子结点大于 sqrt(n) 个的 , 孩子结点小于 sqrt(n) 。

对前面的离线更新, 后面的在线更新 。

/* lys */
#include <bits/stdc++.h>
using namespace std; const int UB = ;
const int N = ;
const int MOD = 1e9 + ; vector<int> nx[N], bnx[N];
int sum[N], out[N]; void Add(int &a, const int b) {
a += b;
if (a >= MOD) {
a -= MOD;
}
} int Run() {
int n; while (cin >> n) {
int x, y; for (int i = ; i <= n; ++i) {
nx[i].clear();
cin >> sum[i];
out[i] = ;
}
for (int i = ; i < n; ++i) {
cin >> x >> y;
nx[x].push_back(y);
nx[y].push_back(x);
}
for (int i = ; i <= n; ++i) {
for (int j = ; j < nx[i].size(); ++j) {
if (nx[nx[i][j]].size() > UB) {
bnx[i].push_back(nx[i][j]);
}
}
}
int m; cin >> m;
for (int i = ; i < m; ++i) {
cin >> x >> y;
if (x == ) {
if (nx[y].size() > UB) {
for (int i = ; i < bnx[y].size(); ++i) {
Add(sum[bnx[y][i]], sum[y]);
}
Add(out[y], sum[y]);
} else {
int s = sum[y]; for (int i = ; i < nx[y].size(); ++i) {
Add(s, out[nx[y][i]]);
}
for (int i = ; i < bnx[y].size(); ++i) {
Add(sum[bnx[y][i]], s);
}
Add(out[y], s);
}
} else {
if (nx[y].size() > UB) {
cout << sum[y] << endl;
} else {
int s = sum[y]; for (int i = ; i < nx[y].size(); ++i) {
Add(s, out[nx[y][i]]);
}
cout << s << endl;
}
}
}
} return ;
} int main() {
ios::sync_with_stdio();
return Run();
}

H:  http://acm.timus.ru/problem.aspx?space=1&num=2031

全过了,忽略

I :http://acm.timus.ru/problem.aspx?space=1&num=2032

blue :
原理就是固定三角形一个点在原点上,那剩下就是找两个点,然后判断一下长度是否符合题目给出的三条边长
根据题目给出的边长A,可以在o(len)找出这些符合条件的点。

就是枚举x坐标,然后看y坐标是否符合,不符合就y--,x越大的话y肯定要越小。同理用同样的方法找出边长B对应的整点。这样找出来满足条件的整点其实数量是很少的。
然后就是枚举这两组顶点的组合,看看这两个点连起来的长度是否为C

/* blue */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
vector<pll> va, vb;
const int dx[] = {,,-,-};
const int dy[] = {,-,,-};
#define x first
#define y second
inline ll sqr(ll x) {return x*x;} int main()
{
ll a,b,c;
while(cin>>a>>b>>c) {
va.clear();
vb.clear();
for(ll i=, j=a; i<=a; i++) {
while(i*i+j*j>a*a) j--;
if(i*i+j*j==a*a) va.push_back(pll(i,j));
}
for(ll i=, j=b; i<=b; i++) {
while(i*i+j*j>b*b) j--;
if(i*i+j*j==b*b) vb.push_back(pll(i,j));
}
for(unsigned i=; i<va.size(); i++) {
for(unsigned j=; j<vb.size(); j++) {
for(int d=; d<; d++) {
if(sqr(va[i].x-vb[j].x*dx[d]) + sqr(va[i].y-vb[j].y*dy[d]) == c*c) {
cout << "0 0" << endl;
cout << va[i].x << ' ' << va[i].y << endl;
cout << vb[j].x*dx[d] << ' ' << vb[j].y*dy[d] << endl;
goto bk;
}
}
}
}
cout << "-1" << endl;
bk: continue;
}
return ;
}

J:  http://acm.timus.ru/problem.aspx?space=1&num=2033    水 , 忽略

K: http://acm.timus.ru/problem.aspx?space=1&num=2034

blue :
首先用BFS求出每个结点离r点的距离,用dis[u]来表示u到r的距离
然后用一次dij来求,额外用一个数组mx[u]表示从s点到u点上,距离最短的是多少。
那从点u到点v的递推关系就是: mx[v] = min(max(mx[v],mx[u]), dis[v])
求完dij以后,答案就是mx[t]了

#include <bits/stdc++.h>
using namespace std;
const int N = ;
const int INF = 1e9;
#define drep(i, l, r) for(int i=l; i<(r); i++)
#define MAX(x, y) (x>y?x:y)
#define MIN(x, y) (x<y?x:y)
#define fi first
#define se second
typedef pair<int,int> pii; int n, m, s, f, r, mx[N], dis[N], d[N];
bool vis[N];
vector<int> g[N]; void bfs(int s) {
memset(vis, , sizeof(vis));
queue<pii> que;
que.push(pii(s, ));
while(!que.empty()) {
int u = que.front().fi;
int l = que.front().se;
que.pop();
if(vis[u]) continue;
vis[u] = ;
dis[u] = l;
for(unsigned i=; i<g[u].size(); i++) {
int &v = g[u][i];
que.push(pii(v, l+));
}
}
} int dij(int s, int t) {
memset(vis, , sizeof(vis));
priority_queue<pii, vector<pii>, greater<pii> > que;
drep(i, , n+) d[i] = INF, mx[i] = -;
d[s] = ;
que.push(pii(, s));
while(!que.empty()) {
int u = que.top().se;
que.pop();
if(vis[u]) continue;
vis[u] = ;
if(mx[u] == -) mx[u] = dis[u];
else mx[u] = MIN(mx[u], dis[u]);
if(u == t) return mx[t];
for(unsigned i=; i<g[u].size(); i++) {
int &v = g[u][i];
if(d[u]+ <= d[v]) {
d[v] = d[u]+;
if(mx[v] == -) mx[v] = mx[u];
else mx[v] = MAX(mx[v], mx[u]);
que.push(pii(d[v], v));
}
}
}
return d[t];
} int main() {
#ifdef LOCAL
freopen("case.txt","r",stdin);
#endif
while(scanf("%d%d", &n, &m)!=EOF) {
drep(i,,n+) g[i].clear();
int u, v;
drep(i, , m) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
scanf("%d%d%d", &s, &f, &r);
bfs(r);
// drep(i, 1, n+1) cout << dis[i] << ' '; cout << endl;
cout << dij(s, f) << endl;
}
}

L:  http://acm.timus.ru/problem.aspx?space=1&num=2035   水 , 忽略

SCAU 2015 GDCPC team_training0的更多相关文章

  1. SCAU 2015 GDCPC team_training1

    A: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1525 题意:前两段都是废话 , 然后给出一个 p( p(a) ) = p(a) 的公式给你 ...

  2. scau 2015寒假训练

    并不是很正规的.每个人自愿参与自愿退出,马哥找题(马哥超nice么么哒). 放假第一周与放假结束前一周 2015-01-26 http://acm.hust.edu.cn/vjudge/contest ...

  3. 2015 西雅图微软总部MVP峰会记录

    2015 西雅图微软总部MVP峰会记录 今年决定参加微软MVP全球峰会,在出发之前本人就已经写这篇博客,希望将本次会议原汁原味奉献给大家 因为这次是本人第一次写会议记录,写得不好的地方希望各位园友见谅 ...

  4. 使用Visual Studio 2015 开发ASP.NET MVC 5 项目部署到Mono/Jexus

    最新的Mono 4.4已经支持运行asp.net mvc5项目,有的同学听了这句话就兴高采烈的拿起Visual Studio 2015创建了一个mvc 5的项目,然后部署到Mono上,浏览下发现一堆错 ...

  5. TFS 2015 敏捷开发实践 – 在Kanban上运行一个Sprint

    前言:在 上一篇 TFS2015敏捷开发实践 中,我们给大家介绍了TFS2015中看板的基本使用和功能,这一篇中我们来看一个具体的场景,如何使用看板来运行一个sprint.Sprint是Scrum对迭 ...

  6. TFS 2015 敏捷开发实践 – 看板的使用

    看板在现代应用开发过程中使用非常广泛,不管是使用传统的瀑布式开发还是敏捷开发,都可以使用看板管理.因为看板拥有简单的管理方法,直观的显示方式,所以很多软件开发团队选择使用看板进行软件开发管理.本文不在 ...

  7. Microsoft Visual Studio 2015 下载、注册、安装过程、功能列表、问题解决

    PS:请看看回复.可能会有文章里没有提到的问题.也许会对你有帮助哦~ 先上一张最终的截图吧: VS2015正式版出了,虽然没有Ultimate旗舰版,不过也是好激动的说.哈哈.可能有的小伙伴,由于工作 ...

  8. 一年之计在于春,2015开篇:PDF.NET SOD Ver 5.1完全开源

    前言: 自从我2014年下半年到现在的某电商公司工作后,工作太忙,一直没有写过一篇博客,甚至连14年股票市场的牛市都错过了,现在马上要过年了,而今天又是立春节气,如果再不动手,那么明年这个无春的年,也 ...

  9. .NET开源进行时:消除误解、努力前行(本文首发于《程序员》2015第10A期的原始版本)

    2014年11月12日,ASP.NET之父.微软云计算与企业级产品工程部执行副总裁Scott Guthrie,在Connect全球开发者在线会议上宣布,微软将开源全部.NET核心运行时,并将.NET ...

随机推荐

  1. Python内置函数之filter map reduce

    Python内置函数之filter map reduce 2013-06-04 Posted by yeho Python内置了一些非常有趣.有用的函数,如:filter.map.reduce,都是对 ...

  2. Spring源码构建

    1.下载spring源码并解压 https://codeload.github.com/spring-projects/spring-framework/zip/v5.0.2.RELEASE 打开bu ...

  3. codevs 1160 蛇形矩阵x

    题目描述 Description 小明玩一个数字游戏,取个n行n列数字矩阵(其中n为不超过100的奇数),数字的填补方法为:在矩阵中心从1开始以逆时针方向绕行,逐圈扩大,直到n行n列填满数字,请输出该 ...

  4. python 存取字典dict

    数据处理的时候主要通过两个函数(1):np.save(“test.npy”,数据结构) ----存数据(2):data =np.load('test.npy") ----取数据 1.存列表 ...

  5. Sonys TRC save data plolicy

    帖子地址:https://forums.unrealengine.com/showthread.php?130820-Sonys-TRC-save-data-plolicy we had severa ...

  6. [CSP-S模拟测试]:玩具(概率DP)

    题目描述 这个故事发生在很久以前,在$IcePrincess\text{_}1968$和$IcePrince\text{_}1968$都还在上幼儿园的时候. $IcePrince\text{_}196 ...

  7. 如何为我们的程序编写开发文档——Java文档注释

    Java文档注释是用于生成Java API文档的注释,通过在程序中的类.属性.方法部分加上注释,就可以用javadoc命令生成漂亮的API文档,是程序员进阶的必备技能. 注意,文档注释只说明紧跟其后的 ...

  8. 【l转】VS2015下解决:无法解析的外部符号 __imp___vsnprintf 及__iob_func

    https://blog.csdn.net/hebbely/article/details/53780562

  9. unity项目中使用BUGLY遇到的的几个问题

    1,第一次对外测试中,发现某些机型游戏中卡死了,但bugly上没报错.后来发现是我们的代码使用 try catch把异常捕获了但什么都没做. 2,别人家项目的bugly上报都能显示出文件和代码行,我们 ...

  10. React Native商城项目实战12 - 首页头部内容

    1.HomeTopView为首页头部内容,HomeTopListView为HomeTopView子视图. 2.HomeTopView.js /** * 首页头部内容 */ import React, ...