B-Basic Gcd Problem
题意:给c和x 求下面这个表达式的值
思路:画一画可以得出公式是 c x 的 质 因 数 个 数 c^{x的质因数个数} cx的质因数个数 ,用线性筛和快速幂来做。
#include <bits/stdc++.h>
using namespace std;
const int N = 1000000, mod = 1e9+7;
int _, n, c, isnot[N+6];
int gcr[N+6];
void getys(){
for(int i=2;i <= N;i++){
if(!isnot[i]) {
for (int j = i; j <= N; j += i) {
isnot[j] = true;
int t = j;
while(t%i==0) {t /= i; gcr[j]++;}
}
}
}
}
long long qpow(long long x, long long n) {
long long res = 1;
for (; n; n >>= 1, x = x * x % mod)
if (n & 1) res = res * x % mod;
return res;
}
int main() {
getys();
scanf("%d", &_);
while(_--) {
scanf("%d %d", &n, &c);
printf("%lld\n", qpow(c, gcr[n]));
}
}
F-Finding the Order
题意:给出四个点,AB在一条线上,CD在一条线上。给出AC,AD,BC,BD 的距离,求出是点 CD 的顺序是 “CD” 还是 “DC”
思路:把这些线连接起来看一下有什么特点,可以发现四条线组成了两个三角形。如下图所示,AD与BC形成的是两个三角形的的两两条边,AC与BD构成两个三条边的斜边,根据三角形的边的性质。就可以得出答案了。
#include <bits/stdc++.h>
using namespace std;
int _, a, b, c, d;
int main() {
scanf("%d", &_);
while(_--) {
scanf("%d %d %d %d", &a, &b, &c, &d);
if(b+c>a+d) puts("AB//CD");
else puts("AB//DC");
}
}
H-Harder Gcd Problem
题意:在 ( 1 , 2 , 3 , . . . , n ) (1,2,3,...,n) (1,2,3,...,n) 中找到大小为m的两个子集,这两个子集对应的点的最大公因数 > 1 > 1 >1 ,求m和具体的子集。
思路:从 n 2 \frac{n}{2} 2n 开始预处理,找到 [ 1 , n 2 ] [1,\frac{n}{2}] [1,2n] 这里面的素数的所有的倍数,存起来,然后遍历每一个这里面的素数,让他们两两一对;如果出现有奇数的情况那么将这里面是偶数的数添加进入2的倍数里面就可以把浪费减小到最小。
拿22来举例看一下:
11 22
7 14 21
5 10 15 20
3 6 9 12 18
2 4 8 16
这个就是预处理的22以内的素数的所有倍数(重复的数只出现一次),然后我们开始更新答案
第一行 11 , 22 11, 22 11,22 可以
第二行有三个数,选择 7 , 21 7,21 7,21 , 将为偶数的14加入2的那一行,更新为:
11 22
7 21
5 10 15 20
3 6 9 12 18
2 4 8 16 14
第三行四个数都可以加入答案
第四行多出一个数,将6加入2那一行,更新为
11 22
7 21
5 10 15 20
3 9 12 18
2 4 8 16 14 6
然后第五行六个数都可以,所以答案为9
#include <bits/stdc++.h>
using namespace std;
int _, n;
const int M = 200005;
vector <int> g[M];
vector <pair<int, int> > ans;
bool isprime[M], vis[M];
void solve() {
for(int i = 1;i <= M; i++) isprime[i] = 1;
for(int i = 3;i <= M; i++) if(!(i%2)) isprime[i] = 0;
for(int i = 2;i <= M; i++) {
if(isprime[i]) {
for(int j = i*2; j<= M; j += i)
isprime[j] = 0;
}
}
isprime[1] = 0;
}
int main() {
solve();
scanf("%d", &_);
while(_--) {
scanf("%d", &n);
ans.clear();
for(int i = 1;i <= n; i++) g[i].clear(), vis[i] = 0;
int num = 0;
for(int i = 2;i <= n/2; i++) {
if(isprime[i]) {
for(int j = i;j <= n; j+=i) {
g[num].push_back(j);
}
num++;
}
}
vector <int> t, nic;
for(int i = num-1;i >= 0; i--) {
t.clear(); nic.clear();
for(auto j: g[i]) {
if(vis[j]) continue;
vis[j] = 1;
t.push_back(j);
}
if(t.size()%2==0) nic = t;
else {
bool ok = 0;
for(auto j: t) {
if(!ok && j%2==0) ok = 1, vis[j] = 0;
else nic.push_back(j);
}
}
for(int j = 1;j < nic.size(); j += 2) {
ans.push_back(make_pair(nic[j-1], nic[j]));
}
}
printf("%d\n", (int)ans.size());
for(auto i: ans) {
printf("%d %d\n", i.first, i.second);
}
}
}