题意:给定一个整数序列,长度为n。每个数 a i a_i ai能与 a i + k a_{i + k} ai+k交换位置,是否能将该序列变换为升序。
思路:该序列可分为k个子序列:
- a 0 , a 0 + k , a 0 + 2 k , . . . , a_0,a_{0+k}, a_{0+2k}, ... , a0,a0+k,a0+2k,...,
- a 1 , a 1 + k , a 1 + 2 k , . . . , a_1,a_{1+k}, a_{1+2k}, ... , a1,a1+k,a1+2k,...,
…- a k − 1 , a k − 1 + k , a l − 1 + 2 k , . . . , a_k-1,a_{k-1+k}, a_{l-1+2k}, ... , ak−1,ak−1+k,al−1+2k,...,
将这k个序列内部排序,放回原序列,判断原序列是否为升序。
Code:
// Problem: C - K Swap
// Contest: AtCoder - AtCoder Beginner Contest 254
// URL: https://atcoder.jp/contests/abc254/tasks/abc254_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
/*
author: A Fei
*/
#include
#define x first
#define y second
#define pi acos(-1)
#define endl '\n'
#define ios ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mem(x, a) memset(x, a, sizeof x)
#define pb(x) push_back(x)
#define rep(i, l, r) for(int i = l; i <= (r); ++ i)
#define per(i, r, l) for(int i = r; i >= (l); -- i)
using namespace std;
typedef long long LL;
typedef double DB;
typedef pair PII;
typedef pair PID;
typedef pair PDD;
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
const int INF = 0x3f3f3f3f;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const int N = 2e5 + 10;
int n, k;
int main()
{
ios;
cin >> n >> k;
vector a(n);
rep(i, 0, n - 1) cin >> a[i];
vector c(n);
rep(i, 0, k - 1)
{
vector b;
for(int j = i; j < n; j += k) b.pb(a[j]);
sort(b.begin(), b.end());
for(int j = 0; j < b.size(); j ++) c[i + j * k] = b[j];
}
// for(auto x : c) cout << x << ' ';
// cout << endl;
if(is_sorted(c.begin(), c.end())) cout << "Yes\n";
else cout << "No\n";
return 0;
}
题意:找出有多少对儿: i , j i, j i,j,使得 i ∗ j i * j i∗j为平方数。( 1 < = i , j < = n 1 <= i, j <= n 1<=i,j<=n)
思路:
可以考虑每个数都可分解质因子变为:
设 N 分 解 质 因 子 为 : N = p 1 a 1 ∗ p 2 a 2 ∗ ⋯ ∗ p n a n 其 中 p 1 , p 2 , ⋯ , p n 为 N 的 质 因 子 则 N 的 约 数 个 数 为 : f ( N ) = ( a 1 + 1 ) ∗ ( a 2 + 1 ) ∗ ⋯ ∗ ( a n + 1 ) 设N分解质因子为: \\N = p_1^{a_1} * p_2^{a_2} *\cdots*p_n^{a_n}\\其中p_1,p_2,\cdots,p_n为N的质因子\\ 则N的约数个数为:f(N) = (a_1 + 1) * (a_2 + 1) * \cdots* (a_n + 1) 设N分解质因子为:N=p1a1∗p2a2∗⋯∗pnan其中p1,p2,⋯,pn为N的质因子则N的约数个数为:f(N)=(a1+1)∗(a2+1)∗⋯∗(an+1)
将该数中奇数个的质因子的积(记为 X i X_i Xi)拿出来计数(记为 C i C_i Ci)。例:
6: 2 1 ∗ 3 1 2^1 * 3^1 21∗31 --> 2 ∗ 3 = 6 2 * 3 = 6 2∗3=6
24: 2 3 ∗ 3 1 2^3 * 3^1 23∗31 --> 2 ∗ 3 = 6 2 * 3 = 6 2∗3=6
6 ∗ 24 = 144 = 1 2 2 6 * 24 = 144 = 12 ^ 2 6∗24=144=122
所以当 i , j i, j i,j的 X X X相同时,说明 i ∗ j i * j i∗j的质因子个数都是偶数,即 i ∗ j i * j i∗j 为平方数。答案为: C 1 2 + C 2 2 + . . . + C i 2 C_1^2 + C_2^2 + ... + C_i^2 C12+C22+...+Ci2。
Code:
// Problem: D - Together Square
// Contest: AtCoder - AtCoder Beginner Contest 254
// URL: https://atcoder.jp/contests/abc254/tasks/abc254_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
/*
author: A Fei
*/
#include
#define x first
#define y second
#define pi acos(-1)
#define endl '\n'
#define ios ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mem(x, a) memset(x, a, sizeof x)
#define pb(x) push_back(x)
#define rep(i, l, r) for(int i = l; i <= (r); ++ i)
#define per(i, r, l) for(int i = r; i >= (l); -- i)
using namespace std;
typedef long long LL;
typedef double DB;
typedef pair PII;
typedef pair PID;
typedef pair PDD;
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
const int INF = 0x3f3f3f3f;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int fun(int n)
{
int res = 1;
// i <= n / i -- why?:
// 最多只会存在一个质因子 > sqrt(n), 两个的话 相乘 > n.
// 当我们一直除最后n!=1,此时n就是那个大于sqrt(n)的质因子
for(int i = 2; i <= n / i; i ++)
if(n % i == 0)
{
int cnt = 0;
while(n % i == 0) n /= i, cnt ++;
if(cnt % 2) res *= i;
}
if(n != 1) res *= n;
return res;
}
int main()
{
ios;
int n;
cin >> n;
map mp;
rep(i, 1, n)
{
int res = fun(i);
mp[res] ++;
}
LL ans = 0;
for(auto x : mp) ans += x.y * x.y;
cout << ans << endl;
return 0;
}
题意:给定一个无向图, Q Q Q次询问。
每次询问:一个点走 K K K次,能到达所有边的权值和
思路: 简单BFS or DFS
错因: 数组开小了…
至少开: 2 ( 双 向 边 ) ∗ M = 3 ∗ N 2(双向边) * M = 3*N 2(双向边)∗M=3∗N。
Code:
// Problem: E - Small d and k
// Contest: AtCoder - AtCoder Beginner Contest 254
// URL: https://atcoder.jp/contests/abc254/tasks/abc254_e
// Memory Limit: 1024 MB
// Time Limit: 3500 ms
//
// Powered by CP Editor (https://cpeditor.org)
/*
author: A Fei
*/
#include
#define x first
#define y second
#define pi acos(-1)
#define endl '\n'
#define ios ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mem(x, a) memset(x, a, sizeof x)
#define pb(x) push_back(x)
#define rep(i, l, r) for(int i = l; i <= (r); ++ i)
#define per(i, r, l) for(int i = r; i >= (l); -- i)
using namespace std;
typedef long long LL;
typedef double DB;
typedef pair PII;
typedef pair PID;
typedef pair PDD;
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
const int INF = 0x3f3f3f3f;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const int N = 6e5 + 10, M = 2 * N;
int h[N], ne[M], e[M], idx;
bool st[N];
int n, m;
void add(int a, int b)
{
ne[idx] = h[a], e[idx] = b, h[a] = idx ++;
}
LL bfs(int x, int k)
{
mem(st, false);
queue q;
q.push({x, 0});
LL sum = 0;
st[x] = true;
while(q.size())
{
PII t = q.front();
q.pop();
int x = t.x, y = t.y;
// depth ++;
if(y <= k) sum += x;
for(int i = h[x]; ~i; i = ne[i])
{
int j = e[i];
if(!st[j] && y + 1 <= k) q.push({j, y + 1}), st[j] = true;
}
}
return sum;
}
int main()
{
ios;
mem(h, -1);
cin >> n >> m;
while(m --)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
int q, x, k;
cin >> q;
while(q --)
{
cin >> x >> k;
// cout << x << k << endl;
cout << bfs(x, k) << endl;
}
return 0;
}
题意:给定两个序列:
A 1 , A 2 , A 3 , . . . , A n A_1,A_2,A_3, ... , A_n A1,A2,A3,...,An
B 1 , B 2 , B 3 , . . . , B n B_1,B_2,B_3, ... , B_n B1,B2,B3,...,Bn
给两个坐标: ( a , b ) , ( c , d ) (a, b),(c, d) (a,b),(c,d),分别为矩阵左上角和右下角( 矩 阵 : C i , j = A i + B j 矩阵:C_{i,j} = A_i + B_j 矩阵:Ci,j=Ai+Bj),询问该范围内矩阵的 G C D GCD GCD。
思路:
首先一个序列: G C D ( a 1 , a 2 , . . . , a n ) GCD(a_1, a_2,...,a_n) GCD(a1,a2,...,an) = G C D ( a 1 , a 2 − a 1 , . . . , a n − a n − 1 ) GCD(a_1, a_2 - a_1,...,a_n - a_{n-1}) GCD(a1,a2−a1,...,an−an−1)
即:原序列的最大公约数 = 差分序列的最大公约数。考虑矩阵任一行的数值:
A i + B j , A i + B j + 1 , A i + B j + 2 , A i + B j + 3 A_i+B_j,A_i+B_{j+1},A_i+B_{j+2},A_i+B_{j+3} Ai+Bj,Ai+Bj+1,Ai+Bj+2,Ai+Bj+3
做差分变为:
A i + B j , B j + 1 − B j , B j + 2 − B j + 1 , B j + 3 − B j + 2 A_i+B_j,B_{j+1} - B_{j},B_{j+2} - B_{j+1},B_{j+3} - B_{j + 2} Ai+Bj,Bj+1−Bj,Bj+2−Bj+1,Bj+3−Bj+2
可以发现我们消去了: A i A_i Ai
对于查询的矩阵:
黄色部分的 G C D GCD GCD为: B 的 差 分 序 列 [ b + 1 , d ] B的差分序列[b+1,d] B的差分序列[b+1,d]的 g c d 1 gcd_1 gcd1.
左边蓝色的 G C D GCD GCD同理为: A 的 差 分 序 列 [ a + 1 , c ] A的差分序列[a+1,c] A的差分序列[a+1,c]的 g c d 2 gcd_2 gcd2.
综上矩阵的 g c d gcd gcd为: G C D ( g c d 1 , g c d 2 , A a + B b − 空 白 快 ) GCD(gcd_1,gcd_2,A_a+B_b-空白快) GCD(gcd1,gcd2,Aa+Bb−空白快)故可以用两个线段树维护两个序列的差分序列的 g c d gcd gcd。
Code:
// Problem: F - Rectangle GCD
// Contest: AtCoder - AtCoder Beginner Contest 254
// URL: https://atcoder.jp/contests/abc254/tasks/abc254_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
/*
author: A Fei
*/
#include
#define x first
#define y second
#define pi acos(-1)
#define endl '\n'
#define ios ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mem(x, a) memset(x, a, sizeof x)
#define pb(x) push_back(x)
#define rep(i, l, r) for(int i = l; i <= (r); ++ i)
#define per(i, r, l) for(int i = r; i >= (l); -- i)
using namespace std;
typedef long long LL;
typedef double DB;
typedef pair PII;
typedef pair PID;
typedef pair PDD;
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
const int INF = 0x3f3f3f3f;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const int N = 2e5 + 10;
struct Node
{
int l, r;
int gcdd;
}tr_a[4 * N], tr_b[4 * N];
int n, Q;
int a[N], b[N], da[N], db[N];
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
void pushup(Node tr[], int u)
{
int l = u << 1, r = u << 1 | 1;
tr[u].gcdd = gcd(tr[l].gcdd, tr[r].gcdd);
}
void build(Node tr[], int t[], int u, int l, int r)
{
tr[u] = {l, r};
if(l == r)
{
tr[u] = {l, l, t[l]};
// cout << l << ' ' << r << ' ' << t[l] << endl;
return ;
}
int mid = l + r >> 1;
build(tr, t, u << 1, l, mid), build(tr, t, u << 1 | 1, mid + 1, r);
pushup(tr, u);
}
Node query(Node tr[], int u, int l, int r)
{
if(l > r) return {0, 0, 0};
if(l <= tr[u].l && tr[u].r <= r) return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
if(r <= mid) return query(tr, u << 1, l, r);
else if(l > mid) return query(tr, u << 1 | 1, l, r);
else
{
Node left, right, res;
left = query(tr, u << 1, l, r);
right = query(tr, u << 1 | 1, l, r);
res.gcdd = gcd(left.gcdd, right.gcdd);
return res;
}
}
int main()
{
ios;
cin >> n >> Q;
rep(i, 1, n) cin >> a[i];
rep(i, 1, n) cin >> b[i];
rep(i, 1, n) da[i] = a[i] - a[i - 1];
rep(i, 1, n) db[i] = b[i] - b[i - 1];
// rep(i, 1, n) cout << da[i] << ' ';
// cout << endl;
// rep(i, 1, n) cout << db[i] << ' ';
// cout << endl;
build(tr_a, da, 1, 1, n);
build(tr_b, db, 1, 1, n);
while(Q --)
{
int r1, r2, c1, c2;
cin >> r1 >> r2 >> c1 >> c2;
int g1 = query(tr_b, 1, c1 + 1, c2).gcdd;
int g2 = gcd(a[r1] + b[c1], query(tr_a, 1, r1 + 1, r2).gcdd);
cout << abs(gcd(g1, g2)) << endl;
// cout << a[r1] + b[c1] << ' ' << g1 << ' ' << g2 << endl;
}
return 0;
}