hdu4431 Mahjong
hdu4432 Sum of divisors
日麻XD
枚举/模拟,之前用一个桶来装牌来搜索结果一直TLE,后来改了一种更直接的搜索方法就可以AC了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 34
int cnt[N] , save[N];
int ans[N] , s;
bool qdz()
{
int i , sum = 0;
for (i = 0 ; i < 34 ; ++ i)
sum += cnt[i] == 2;
return sum == 7;
}
bool gsws()
{
int i , sum = 0 , sum2 = 0;
for (i = 0 ; i < 34 ; ++ i)
if (i >= 27 || i % 9 == 0 || i % 9 == 8)
sum += cnt[i] == 1 , sum2 += cnt[i] == 2;
return sum == 12 && sum2 == 1;
}
int p[N];
bool f[N];
bool dfs(int dep)
{
if (dep == 4) return 1;
int i , j , k;
for (i = 0 ; f[i] ; ++ i);
for (j = i + 1 ; j < 12 ; ++ j)
if (!f[j] && p[j] == p[i]) break;
for (k = j + 1 ; k < 12 ; ++ k)
if (!f[k] && p[k] == p[i]) break;
if (j < 12 && k < 12)
{
f[i] = f[j] = f[k] = 1;
if (dfs(dep + 1)) return 1;
f[i] = f[j] = f[k] = 0;}
if (p[i] < 27 && p[i] % 9 < 7)
{
for (j = i + 1 ; j < 12 ; ++ j)
if (!f[j] && p[j] == p[i] + 1) break;
for (k = j + 1 ; k < 12 ; ++ k)
if (!f[k] && p[k] == p[i] + 2) break;
if (j < 12 && k < 12)
{
f[i] = f[j] = f[k] = 1;
if (dfs(dep + 1)) return 1;
f[i] = f[j] = f[k] = 0;}
}
return 0;
}
void work()
{
int i , j , k , x; char ma[5];
memset(cnt , 0 , sizeof(cnt));
for (i = 0 ; i < 13 ; ++ i)
{
scanf("%s" , ma);
if (ma[1] == 'm') j = 0;
if (ma[1] == 's') j = 1;
if (ma[1] == 'p') j = 2;
if (ma[1] == 'c') j = 3;
++ cnt[j * 9 + *ma - '1'];
}
memcpy(save , cnt , sizeof(cnt));
s = 0;
for (i = 0 ; i < 34 ; ++ i)
{
if (cnt[i] < 4)
{
++ cnt[i];
if (qdz() || gsws())
{
ans[s ++] = i;
-- cnt[i];
continue;
}
for (j = 0 ; j < 34 ; ++ j)
if (cnt[j] >= 2)
{
cnt[j] -= 2;
x = 0; memset(f , 0 , sizeof(f));
for (k = 0 ; k < 34 ; ++ k)
for (int l = 0 ; l < cnt[k] ; ++ l)
p[x ++] = k;
if (dfs(0)) break;
cnt[j] += 2;
}
if (j < 34) ans[s ++] = i;;
memcpy(cnt , save , sizeof(cnt));
}
}
if (!s)
puts("Nooten");
else
{
printf("%d " , s);
for (i = 0 ; i < s ; ++ i)
printf("%c%c%c" , ans[i] % 9 + '1' , "mspc"[ans[i] / 9] , " \n"[i == s - 1]);
}
}
int main()
{
int _; scanf("%d" , &_); while (_--)
//while (~scanf("%d",&n))
work();
return 0;
}
hdu4432 Sum of divisors
sqrt{n}枚举因子,直接统计。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
int n , m ;
int cal(int x)
{
int sum = 0 , i;
while (x)
i = x % m , sum += i * i , x /= m;
return sum;
}
vector<int> digit;
void work()
{
int i ; LL ans = 0; digit.clear();
for (i = 1 ; i * i <= n ; ++ i)
if (n % i == 0)
{
ans += cal(i);
if (i * i != n)
ans += cal(n / i);
}
while (ans)
digit.push_back(ans % m) , ans /= m;
for (i = digit.size() - 1 ; i >= 0 ; -- i)
if (digit[i] < 10)
printf("%d" , digit[i]);
else putchar(digit[i] - 10 + 'A');
puts("");
}
int main()
{
while (~scanf("%d%d",&n,&m))
work();
return 0;
}
hdu4433 locker
f[i][j][k]表示前i位归位第i+1位为j第i+2位为k的最小步数。
可以给a和b末尾加两个0来避免可能的特判
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 1005
char a[N] , b[N];
int n , f[N][10][10];
void work()
{
int i , j , k , l , x , y , z;
n = strlen(a + 1);
a[++ n] = '0' , b[n] = '0';
a[++ n] = '0' , b[n] = '0';
a[n + 1] = 0 , b[n + 1] = 0;
for (i = 0 ; i <= n ; ++ i)
{
a[i] -= '0' , b[i] -= '0';
for (j = 0 ; j < 10 ; ++ j)
for (k = 0 ; k < 10 ; ++ k)
f[i][j][k] = 1 << 30;
}
f[0][a[1]][a[2]] = 0;
for (i = 1 ; i <= n - 2 ; ++ i)
{
for (j = 0 ; j < 10 ; ++ j)
for (k = 0 ; k < 10 ; ++ k)
if (f[i - 1][j][k] < 1 << 30)
// i -> j , i + 1 -> k
{
z = (10 + b[i] - j) % 10;
for (x = 0 ; x <= z ; ++ x)
for (y = 0 ; y <= x ; ++ y)
f[i][(k + x) % 10][(a[i + 2] + y) % 10] = min(f[i][(k + x) % 10][(a[i + 2] + y) % 10] , f[i - 1][j][k] + z);
z = (10 + j - b[i]) % 10;
for (x = 0 ; x <= z ; ++ x)
for (y = 0 ; y <= x ; ++ y)
f[i][(k - x + 10) % 10][(a[i + 2] - y + 10) % 10] = min(f[i][(k - x + 10) % 10][(a[i + 2] - y + 10) % 10] , f[i - 1][j][k] + z);
}
}
cout << f[n - 2][0][0] << endl;
}
int main()
{
while (~scanf("%s%s", a+1, b+1))
work();
return 0;
}
hdu4435 charge-station
贪心,从大到小看一个加油站的存在是否是必要的,判断答案的时候用BFS求出达到没有油站的点的最小耗油数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 128
int n , X[N] , Y[N] , D , g[N][N];
bool build[N] , f[N];
int d[N];
bool check()
{
int i , x , y;
memset(f , 0 , sizeof(f));
for (i = 0 ; i < n ; ++ i)
if (build[i])
d[i] = 0;
else d[i] = 1 << 29;
queue<int> Q; Q.push(0) , f[0] = 1;
while (!Q.empty())
{
x = Q.front() , Q.pop();
for (y = 0 ; y < n ; ++ y)
if (!f[y] && g[x][y] <= D)
{
d[y] = min(d[y] , d[x] + g[x][y]);
if (build[y])
f[y] = 1 , Q.push(y);
}
}
for (i = 0 ; i < n ; ++ i)
if (build[i] && !f[i] || !build[i] && d[i] + d[i] > D)
return 0;
return 1;
}
void work()
{
int i , j;
for (i = 0 ; i < n ; ++ i)
scanf("%d%d",&X[i],&Y[i]);
for (i = 0 ; i < n ; ++ i)
for (j = i + 1 ; j < n ; ++ j)
g[i][j] = g[j][i] = ceil(sqrt((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j])) - 1e-9);
memset(build , 1 , sizeof(build));
if (!check())
puts("-1");
else
{
for (i = n - 1 ; i >= 0 ; -- i)
{
build[i] = 0;
if (!check())
build[i] = 1;
}
for (i = n - 1 ; !build[i] ; -- i);
for ( ; i >= 0 ; -- i) printf("%d" , build[i]);
puts("");
}
}
int main()
{
while (~scanf("%d%d", &n, &D))
work();
return 0;
}
hdu4436 str2int
求出后缀数组之后,对每个串的后缀都线性递推出其所有前缀代表的数字之和,就有一个明显的递推关系。
累计答案的时候不需要考虑0开头的后缀,也不需要考虑之前有重复的LCP。
在纸上推推式子就能推出来,不是很难。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 110005
int n , m ; int s[N];
int sa[N] , t1[N] , t2[N] , c[N];
int rank[N] , height[N];
void buildsa(int m)
{
int i , k , *x = t1 , *y = t2;
for (i = 0 ; i < m ; ++ i) c[i] = 0;
for (i = 0 ; i < n ; ++ i) ++ c[x[i] = s[i]];
for (i = 1 ; i < m ; ++ i) c[i] += c[i - 1];
for (i = n - 1 ; i >= 0 ; -- i) sa[-- c[x[i]]] = i;
for (k = 1 ; k <= n ; k <<= 1)
{
int p = 0;
for (i = n - k ; i < n ; ++ i) y[p ++] = i;
for (i = 0 ; i < n ; ++ i) if (sa[i] >= k) y[p ++] = sa[i] - k;
for (i = 0 ; i < m ; ++ i) c[i] = 0;
for (i = 0 ; i < n ; ++ i) ++ c[x[y[i]]];
for (i = 1 ; i < m ; ++ i) c[i] += c[i - 1];
for (i = n - 1 ; i >= 0 ; -- i) sa[-- c[x[y[i]]]] = y[i];
swap(x , y) , p = 1 , x[sa[0]] = 0;
for (i = 1 ; i < n ; ++ i)
x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]) ? p - 1 : p ++;
if (p >= n) break;
m = p;
}
k = 0;
for (i = 0 ; i < n ; ++ i) rank[sa[i]] = i;
for (i = 0 ; i < n ; ++ i)
{
if (k) -- k; if (!rank[i]) continue;
int j = sa[rank[i] - 1];
while (s[i + k] == s[j + k]) ++ k;
height[rank[i]] = k;
}
}
char str[N];
int f[N] , power[N] , id[N] , num[N] , p10[N];
int Q = 2012;
void work()
{
int i , j , k , x , y , len , sum = 0;
n = 0;
memset(f , 0 , sizeof(f));
memset(id , 0 , sizeof(id));
memset(num , 0 , sizeof(num));
for (i = 1 ; i <= m ; ++ i)
{
scanf("%s" , str);
len = strlen(str);
for (j = len - 1 , k = 0 ; j >= 0 ; -- j , ++ k)
{
f[n + j] = f[n + j + 1] + power[k] * (str[j] - '0') , f[n + j] %= Q;
id[n + j] = k;
}
for (k = 0 ; k < len ; ++ k)
num[n + k + 1] = (k ? num[n + k] : 0) * 10 + str[k] - '0' , num[n + k + 1] %= Q;
for (j = 0 ; str[j] ; ++ j)
s[n ++] = m + 1 + str[j] - '0';
s[n ++] = i;
}
buildsa(m + 15);
int st = 0;
while (st < n && s[sa[st]] <= m + 1) ++ st;
for (i = st ; i < n ; ++ i)
{
j = height[i];
sum += f[sa[i] + j] + (num[sa[i]+j] - num[sa[i]] * p10[j] % Q + Q) % Q * (power[id[sa[i]] - j + 1] + 2011) % Q;
sum %= Q;
}
cout << sum << endl;
}
int main()
{
power[0] = p10[0] = 1;
for (int i = 1 ; i <= 110002 ; ++ i)
power[i] = power[i - 1] * 10 + 1 , power[i] %= Q ,
p10[i] = p10[i - 1] * 10 , p10[i] %= Q;
while (~scanf("%d", &m))
work();
return 0;
}
hdu4438 Hunters直接可以计算出两个期望,比较输出。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 1005
char a[N] , b[N];
int n , f[N][10][10];
void work()
{
double x , y , p , q , a , b;
scanf("%lf%lf%lf%lf",&x,&y,&p,&q);
a = q * p * (x + y) + (1 - q) * x;
b = q * y + (1 - q) * p * (x + y);
if (a > b)
printf("tiger %.4f\n" , a);
else printf("wolf %.4f\n" , b);
}
int main()
{
//freopen("~input.txt" , "r" , stdin);
//freopen("output.txt" , "w" , stdout);
int _; scanf("%d" , &_); while (_--)
//while (~scanf("%s%s", a+1, b+1))
work();
return 0;
}
hdu4441 Queue Sequence用splay维护整个数列,用set维护每次insert的数字
insert的p的位置的时候如果1~p之间有k个正数,负数就肯定在第k+1个负数的前一个位置。
剩下两个操作就很简单了。
发现splay用的还是不熟,找第k+1个负数的代码写了很久。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 200005
struct splay_tree
{
int root , nodecnt , c[N][2] , size[N] , par[N] , type[N] , stack[N];
int key[N] , sp[N] , sm[N];
LL sum[N];
int rub[N] , rs;
void clear()
{
root = 0 , size[0] = 0 , type[0] = -1;
c[0][0] = c[0][1] = par[0] = 0;
nodecnt = 0 , rs = 0;
}
int malloc(int k)
{
int x;
if (rs) x = rub[rs --]; else x = ++ nodecnt;
sum[x] = key[x] = k , size[x] = 1 , type[x] = -1;
c[x][0] = c[x][1] = par[x] = 0;
sp[x] = (k > 0) , sm[x] = (k < 0);
return x;
}
void pushdown(int x)
{
}
void pushup(int x)
{
if (!x) return; pushdown(x); pushdown(c[x][0]); pushdown(c[x][1]);
sum[x] = key[x] , size[x] = 1 , sp[x] = (key[x] > 0) , sm[x] = (key[x] < 0);
if(c[x][0]) sum[x] += sum[c[x][0]] , sp[x] += sp[c[x][0]] , sm[x] += sm[c[x][0]] , size[x] += size[c[x][0]];
if(c[x][1]) sum[x] += sum[c[x][1]] , sp[x] += sp[c[x][1]] , sm[x] += sm[c[x][1]] , size[x] += size[c[x][1]];
}
void rotate (int x)
{
int t = type[x] , y = par[x] , z = c[x][t ^ 1];
type[x] = type[y] , par[x] = par[y];
if (~type[x]) c[par[x]][type[x]] = x;
type[y] = t ^ 1 , par[y] = x , c[x][t ^ 1] = y;
if (x) type[z] = t , par[z] = y;
c[y][t] = z , pushup(y);
}
void splay(int x)
{
int cnt = 0 , i; stack[++ cnt] = x;
for (i = x ; ~type[i] ; i = par[i])
stack[++ cnt] = par[i];
for (i = cnt ; i > 0 ; -- i) pushdown(stack[i]);
while (~type[x])
{
int y = par[x];
if (type[x] == type[y])rotate(y) ;else rotate(x);
if (!~type[x]) break;
rotate(x);
}
pushup(x);
}
int Rank(int x)
{
splay(x) , root = x; return size[c[x][0]] + 1;
}
int getKth(int x , int k)
{
while (1)
{
pushdown(x);
if (size[c[x][0]] + 1 == k) break;
if (size[c[x][0]] + 1 > k)
x = c[x][0];
else
k -= size[c[x][0]] + 1 , x = c[x][1];
}
return x;
}
int getKthMin(int x , int k)
{
while (1)
{
pushdown(x);
if (sm[c[x][0]] + (key[x] < 0) >= k)
{
if (sm[c[x][0]] < k) break;
x = c[x][0];
}
else
k -= sm[c[x][0]] + (key[x] < 0) , x = c[x][1];
}
return x;
}
void split(int p , int& x , int& y , int a)
{
if (a == size[p]) {x = p , y = 0;return;}
y = getKth(p , a + 1) , splay(y);
x = c[y][0] , type[x] = -1 , c[y][0] = 0 , par[x] = 0;
pushup(y);
}
void merge(int& p , int x ,int y)
{
if (!x || !y) {p = x | y ; return;} pushdown(x);
p = getKth(x , size[x]) , splay(p) , c[p][1] = y;
type[y] = 1 , par[y] = p , pushup(p);
}
void print(int x)
{
pushdown(x);
if (c[x][0]) print(c[x][0]);
printf("%d ", key[x]);
if (c[x][1]) print(c[x][1]);
}
};
set<int> node;
int cnt , id[N][2];
splay_tree T;
int ca , m;
void work()
{
int i , j , x , y , z , p , q , num; char str[10];
T.clear();
cnt = 0 , node.clear();
printf("Case #%d:\n" , ++ ca);
while (m --)
{
scanf("%s" , str);
if (*str == 'i')
{
scanf("%d",&p);
if (node.size())
i = *node.begin() , node.erase(i);
else i = ++ cnt;
T.split(T.root , x , y , p);
num = T.sp[x];
id[i][0] = z = T.malloc(i);
T.merge(x , x , z);
T.merge(T.root , x , y);
if (T.sm[T.root] == num)
{
id[i][1] = z = T.malloc(-i);
T.merge(T.root , T.root , z);
}
else
{
p = T.Rank(T.getKthMin(T.root , num + 1));
T.split(T.root , x , y , p - 1);
id[i][1] = z = T.malloc(-i);
T.merge(x , x , z);
T.merge(T.root , x , y);
}
}
if (*str == 'r')
{
scanf("%d",&i);
p = T.Rank(id[i][0]);
T.split(T.root , x , y , p - 1);
T.split(y , y , z , 1);
T.merge(T.root , x , z);
T.rub[++ T.rs] = y;
p = T.Rank(id[i][1]);
T.split(T.root , x , y , p - 1);
T.split(y , y , z , 1);
T.merge(T.root , x , z);
T.rub[++ T.rs] = y;
node.insert(i);
}
if (*str == 'q')
{
scanf("%d",&i);
p = T.Rank(id[i][0]);
q = T.Rank(id[i][1]);
T.split(T.root , x , y , p - 1);
T.split(y , y , z , q - p + 1);
printf("%I64d\n" , T.sum[y]);
T.merge(y , y , z);
T.merge(T.root , x , y);
}
// T.print(T.root);puts("");
}
}
int main()
{
while (~scanf("%d",&m))
work();
return 0;
}