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. 借助tcpdump统计http请求

    借助tcpdump统计http请求     这里所说的统计http请求,是指统计QPS(每秒请求数),统计前十条被访问最多的url.一般做这样的统计时,我们经常会使用网站访问日志来统计.当我们来到一个 ...

  2. 缓存算法LRU笔记

      LRU原理与分析 LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,也就是说,LRU缓存把最近最少使用的数据移除,让给最新读取的数据.而往往最常读取的,也是读取 ...

  3. 【leetcode】1074. Number of Submatrices That Sum to Target

    题目如下: Given a matrix, and a target, return the number of non-empty submatrices that sum to target. A ...

  4. linux运维、架构之路-python2.6升级3.6

    一.环境 1.系统 [root@m01 ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@m01 ~]# uname -r -. ...

  5. C#(.net)实现用apache activemq传递SQLite的数据

    版权声明:本文为搜集借鉴各类文章的原创文章,转载请注明出处:http://www.cnblogs.com/2186009311CFF/p/6382623.html. C#(.net)实现用apache ...

  6. bullet学习日记

    最近需要bullet用物理引擎做一个测量类的项目,因为半途接手,物理部分其实已经实现,但犹于对bullet基本不了解,导致相关部分完全改不动,这两天静下心来把物理引擎用法了解了一翻,顺便做点笔记,以便 ...

  7. CSS颜色和长度单位

    颜色 如果我们相给页面设置颜色可以采用多种方法进行设置: 一.命名颜色 假设在设置页面的颜色时觉得一部分很小的颜色集中就足够了,就可以直接给定颜色的名称.CSS称这些有名称的颜色为命名颜色. 命名颜色 ...

  8. 状态管理工具对比vuex、redux、flux

    1.为什么要使用状态管路工具  在跨层级的组件之间传递信息,尤其是复杂的组件会非常困难.也不利于开发和维护,这时我们就a需要用到状态管理工具.     2.Flux

  9. Android使用命令行操作数据库

    所有的应用程序本地文件都存放在/data/data/目录下 C:\Users\nicole>adb shell * daemon not running. starting it now on ...

  10. Internet History, Technology, and Security(week1)——History: Dawn of Electronic Computing

    前言: 第一次进行课程学习,在反复观看视频和查找字典翻译理解后选出了视频中个人认为较重要的概念,以下并不按照逐句翻译,中文概括大意余下自由发挥,对老师想要告诉我们的历史有一个初步的了解,顺便锻炼以下英 ...