1001 AND Minimum Spanning Tree(HDU6614)
题意
要你构造一棵最小生成树,边权是两顶点的编号的与值。
思路
对于(2^i-1)看(2^i)是否小于等于(n),如果是则与(2^i)连边,其他的数则看其二进制下最后一个(0)在哪,假设是在(x),那么就与(2^x)连边。
代码实现如下:
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********
")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1000000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n;
vector<int> vec;
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
int ans = 0;
vec.clear();
for(int i = 2; i <= n; ++i) {
int num = 0;
for(int j = 0; j <= 20; ++j) {
if(i <= (1<<j)) {
num = (1<<j);
break;
}
}
if(i == num - 1) {
if(num <= n) vec.push_back(num);
else vec.push_back(1), ++ans;
} else {
for(int j = 0; j <= 20; ++j) {
if(!(i & (1<<j))) {
vec.push_back((1<<j));
break;
}
}
}
}
printf("%d
", ans);
int flag = 0;
for(int i = 0; i < vec.size(); ++i) {
if(flag) printf(" ");
flag = 1;
printf("%d", vec[i]);
}
printf("
");
}
return 0;
}
1003 Divide the Stones(HDU6616)
题意
要你把个石子分成(k)堆,每堆有(frac{n}{k})个石子,使得这(k)堆石子重量相同,每个石子的重量为(i)。
思路
对于(frac{n}{k})偶数我们发现蛇形填数是可以使得其相等的,那么对于奇数我们只需要拿出前(3k)个来填,剩余的按照偶数的进行处理即可。
奇数的时候我们首先确定第一列分别为(1)~(k),第二列肯定要错位填数,通过计算可以得到第(frac{k}{2}+1)填(2k),然后(frac{k}{2}+2)填(1),以此类推。第三列则用(frac{3(3*k+1)}{3})来减即可。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********
")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1000000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n, k;
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
if(1LL * n * (n + 1) / 2 % k || (n == k && n != 1)) {
printf("no
");
continue;
}
printf("yes
");
int x = k, y = n / k;
int mp[x+5][y+5];
if(y & 1) {
for(int i = 1; i <= x; ++i) mp[i][1] = i;
mp[k/2+1][2] = 2 * k;
for(int i = k / 2 + 2; i <= x; ++i) mp[i][2] = i - k / 2 - 1 + k;
for(int i = 1; i <= k / 2; ++i) mp[i][2] = k + k / 2 + i;
for(int i = 1; i <= x; ++i) mp[i][3] = 4 * k + k / 2 + 2 - mp[i][1] - mp[i][2];
int nx = 1, ny = 4;
for(int i = 3 * k + 1; i <= n; ++i) {
mp[nx][ny] = i;
if(ny % 2 == 0) {
if(nx == x) {
++ny;
} else {
++nx;
}
} else {
if(nx == 1) {
++ny;
} else {
--nx;
}
}
}
} else {
int nx = 1, ny = 1;
for(int i = 1; i <= n; ++i) {
mp[nx][ny] = i;
if(ny % 2 == 1) {
if(nx == x) {
++ny;
} else {
++nx;
}
} else {
if(nx == 1) {
++ny;
} else {
--nx;
}
}
}
}
for(int i = 1; i <= x; ++i) {
for(int j = 1; j <= y; ++j) {
printf("%d%c", mp[i][j], j == y ? '
' : ' ');
}
}
}
return 0;
}
1007 Just an Old Puzzle(HDU6620+华容道+逆序对)
思路
把(0)变成(16)然后矩阵合并成一列求出逆序对,加上(0)的初始位置如果是偶数则可以构造,否则就不能构造。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********
")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1000000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t;
int a[20];
int main() {
scanf("%d", &t);
while(t--) {
int ans = 0;
for(int i = 0; i < 16; ++i) {
scanf("%d", &a[i]);
if(a[i] == 0) ans += i / 4 + 1 + i % 4 + 1;
if(a[i] == 0) a[i] = 16;
for(int j = 0; j <= i; ++j) {
if(a[j] > a[i]) ++ans;
}
}
if(ans & 1) printf("No
");
else printf("Yes
");
}
return 0;
}
1008 K-th Closest Distance(6621+主席树+二分)
题意
对于一个数组(a)查询(q)次,每次问区间([L,R])中距离(p)是第(k)大的是多少(第(i)个数与(p)的距离为(|a_i-p|))。
思路
二分答案然后看([p-ans,p+ans])内有没有(k)个数。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********
")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1000000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n, q, l, r, p, k, cnt;
int a[maxn], root[maxn];
struct node {
int l, r, sum;
}tree[maxn*40];
void update(int l, int r, int &x, int &y, int pos) {
tree[++cnt] = tree[y], tree[cnt].sum++, x = cnt;
if(l == r) return;
int mid = (l + r) >> 1;
if(mid >= pos) update(l, mid, tree[x].l, tree[y].l, pos);
else update(mid + 1, r, tree[x].r, tree[y].r, pos);
}
int query(int l, int r, int x, int y, int L, int R) {
if(l >= L && r <= R) return tree[y].sum - tree[x].sum;
if(l == r) return 0;
int mid = (l + r) >> 1;
if(R <= mid) return query(l, mid, tree[x].l, tree[y].l, L, R);
else if(L > mid) return query(mid + 1, r, tree[x].r, tree[y].r, L, R);
else return query(l, mid, tree[x].l, tree[y].l, L, mid) + query(mid + 1, r, tree[x].r, tree[y].r, mid + 1, R);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
time_t s = clock();
#endif // ONLINE_JUDGE
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &q);
int mx = 0;
cnt = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
mx = max(mx, a[i]);
}
for(int i = 1; i <= n; ++i) {
update(1, mx, root[i], root[i-1], a[i]);
}
int las = 0;
while(q--) {
scanf("%d%d%d%d", &l, &r, &p, &k);
l = l ^ las, r = r ^ las, p = p ^ las, k = k ^ las;
int ub = mx, lb = 0, mid, ans = mx;
while(ub >= lb) {
mid = (ub + lb) >> 1;
if(query(1, mx, root[l-1], root[r], p - mid, p + mid) >= k) {
ans = mid;
ub = mid - 1;
} else {
lb = mid + 1;
}
}
las = ans;
printf("%d
", ans);
}
}
return 0;
}
1010 Minimal Power of Prime(HDU6623+素数筛)
题意
给你(n),问你(n)的素因子中最小的次数是多少。
思路
我们首先把(4000)内的素数筛出来,如果(n)还有剩余那么可以发现除了(p^4,p^3,p^2,(p_1p_2)^2)外其他情况指数最小都是(1),对于这几种情况分别开方就行,最后与小于(4000)的素数的最小次数取(min)就行。
本题与HDU5447(题解)很像,想清楚就会发现其实很简单,根本就不用把(n)完全唯一分解出来。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********
")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 4000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, tot;
LL n;
bool v[maxn];
int p[maxn];
void init() {
for(int i = 2; i < maxn; ++i) {
if(!v[i]) {
p[tot++] = i;
}
for(int j = 0; j < tot && i * p[j] < maxn; ++j) {
v[i*p[j]] = 1;
if(i % p[j] == 0) break;
}
}
}
int main() {
init();
scanf("%d", &t);
while(t--) {
scanf("%lld", &n);
int cnt = inf;
int flag = 0;
for(int i = 0; i < tot; ++i) {
if(n % p[i] == 0) {
int num = 0;
while(n % p[i] == 0) {
++num;
n /= p[i];
}
if(num == 1) {
flag = 1;
}
cnt = min(cnt, num);
}
}
if(flag) {
printf("1
");
continue;
}
if(n == 1) {
printf("%d
", cnt);
continue;
}
LL tmp = pow(n, 0.25);
if(tmp * tmp * tmp * tmp == n) {
cnt = min(cnt, 4);
} else {
++tmp;
if(tmp * tmp * tmp * tmp == n) {
cnt = min(cnt, 4);
} else {
tmp = pow(n, 0.5);
if(tmp * tmp == n) {
cnt = min(cnt, 2);
} else {
++tmp;
if(tmp * tmp == n) {
cnt = min(cnt, 2);
} else {
tmp = pow(n, 1.0 / 3);
if(tmp * tmp * tmp == n) {
cnt = min(cnt, 3);
} else {
++tmp;
if(tmp * tmp * tmp == n) {
cnt = min(cnt, 3);
} else {
cnt = min(cnt, 1);
}
}
}
}
}
}
printf("%d
", cnt);
}
return 0;
}