Lonely Numbers (CodeForces - 1423K )
题意
首先给出一个定义:若两个数a,b满足以gcd(a,b),a/gcd(a,b),b/gcd(a,b)的值为边长的三条边能够组成一个三角形,则称a,b为友好数。先给出一个正整数n,问从1~n中有多少个数无法与给出的其他数字组成友好数
思路
借鉴dalao的思路: 点击跳转
一、如果一个数为质数,那么这个质数的友好数只有可能是它的平方
证明:设一个质数x的友好数为y
①当(y%x!=0)时,三条边长度分别为1,x,y,最短边为1,只有当x== y时才能组成三角形,显然不成立
②当(y%x == 0 && y/x=k)时,三条边长度分别为x,1,k,与①同理,只有当x==k是才能组成三角形,此时y=x*x
二、如果一个数为合数,那么这个数一定可以在比它小的数中找到友好数
证明:设一个合数x的友好数为y
①若x为某质数的平方,则可由(一)证
②若x不为质数的平方,可将其分解为x=ab (其中a<=b),那么取y=a(b-1),那么x与y可产生三条边a,b,b-1,因为合数的因数a与b满足 a>=b>1 ,所以这三条边一定可以组成一个三角形
那么我们只需要统计1~n中出现的特定质数(该质数的平方<n)的个数,运用欧拉筛与差分即可
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int prime[N], ans[N];
bool st[N];
int main() {
int k = 0;
for (int i = 2; i <= N; i++) {
if (!st[i])
prime[++k] = i;
for (int j = 1; prime[j] <= N / i; j++) {
st[prime[j] * i] = true;
if (i % prime[j] == 0)
break;
}
}
for (int i = 1; i <= k; i++) {
if (prime[i] <= 1000)
ans[prime[i] * prime[i]]--;
ans[prime[i]]++;
}
ans[1] = 1;
for (int i = 2; i < N; i++)
ans[i] += ans[i - 1];
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
printf("%d\n", ans[n]);
}
return 0;
}
Nice Matrix (CodeForces - 1422B )
题意
给出一个n*m的矩阵,给矩阵中每个元素加上或减去某个值,使其变为一个回文矩阵(每一个元素对应的行与列都是回文串),求这些值的绝对值总和最少可以为多少
思路
找出该元素分别对应行与列中的对称位置的两个元素,然后找出这三个元素的中位数,将另外两个数变为这个中位数,将变化的值累加就是最优解
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 105;
LL g[N][N];
void solve() {
LL n, m, ans = 0;
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%lld", &g[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
vector<int> t;
t.push_back(g[i][j]);
t.push_back(g[i][m - j + 1]);
t.push_back(g[n - i + 1][j]);
sort(t.begin(), t.end());
g[i][j] = g[i][m - j + 1] = g[n - i + 1][j] = t[1];
ans += (t[1] - t[0] + t[2] - t[1]);
}
printf("%lld\n", ans);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}