题意:给出一个整数 n n n(1e9范围内),给出条件 a + b = n a+b=n a+b=n,要使得 l c m ( a , b ) lcm(a,b) lcm(a,b)最小,输出 a a a和 b b b。
做法:结论是其中一个答案是 n n n的最大因子(由于不会证明被拖出去枪毙 ),找了找官方题解的证明,总结(翻译 )了一下证明如下:
令 a = k , b = n − k a=k,b=n-k a=k,b=n−k,假设 k ≤ n − k k≤n-k k≤n−k,意味着 n − k ≥ n 2 n-k≥ \frac{n}{2} n−k≥2n;
如果 k ∣ n k|n k∣n,即存在 m ∗ k = n , n − k = m ∗ k − k = ( m − 1 ) ∗ k m*k=n,n-k=m*k-k=(m-1)*k m∗k=n,n−k=m∗k−k=(m−1)∗k,这时可得 l c m ( k , n − k ) = n − k < n lcm(k, n-k)=n-k
如果 k † n k\dagger n k†n,且 k † n − k k\dagger n-k k†n−k,那么 l c m ( k , n − k ) ≠ n − k lcm(k,n-k) \ne n-k lcm(k,n−k)=n−k,且 l c m ( k , n − k ) lcm(k, n-k) lcm(k,n−k)会是 k k k和 n − k n-k n−k的乘积,这时 l c m ( k , n − k ) ≥ 2 ∗ ( n − k ) ≥ 2 ∗ n 2 = n lcm(k,n-k)≥2*(n-k)≥2*\frac{n}{2} = n lcm(k,n−k)≥2∗(n−k)≥2∗2n=n;
k ∣ n k|n k∣n时 l c m < n lcm
代码:
#include
using namespace std;
typedef long long LL;
LL res = 1e18;
int main() {
int t; scanf("%d", &t);
int n;
while(t--) {
scanf("%d", &n);
int a, b, ans = n - 1;
for(int i = 1; i*i <= n; ++i) {
if(n % i == 0) {
ans = min(ans, n-i);
if(i != 1) ans = min(ans, n-n/i);
}
}
printf("%d %d\n", ans, n-ans);
}
return 0;
}
题意:有一种操作,会使得一个区间内所有数字位置都和原来位置不同,问最少多少次操作能使得长度为 n n n(2e5范围内)的全排列变为 1 − n 1-n 1−n的顺序排列。
做法:一共是三种情况:
首先排除首尾已经在本位上的数字。
1、对于已经排好序的排列结果就是 0 0 0
2、对于完全打乱的排列只需要 1 1 1次操作就能恢复顺序排列。
3、对于部分打乱的排列结果是 2 2 2,第一次让所有位置的都打乱,使得部分打乱的数字能回到原位,第二次还原原本就在本位上的数字,一共两次。
代码:
#include
using namespace std;
typedef long long LL;
const int N = 2e5+10;
int a[N];
int main() {
int t; scanf("%d", &t);
int n;
while(t--) {
deque<int> dq;
scanf("%d", &n);
for(int i = 1, x; i <= n; ++i) {
scanf("%d", &x);
a[i] = 0; if(x == i) a[i] = 1;
}
//排除首位已经排好序的
int lo = 1, hi = n;
while(lo <= hi && a[lo]) ++lo;
while(lo <= hi && a[hi]) --hi;
if(lo > hi) {
puts("0"); continue;
}
int res = 0;
for(int i = lo; i <= hi; ++i) {
if(!a[i]) ++res;
}
if(res == hi-lo+1) puts("1");
else if(res) puts("2");
}
return 0;
}
题意:有 n n n(2e5范围内且一定是奇数)个数字组成一个环,可以采用的操作是选取一个数字,用与他相邻的两个数字的和代替他自己,然后删掉相邻的两个数字,重复该操作,直到最后只剩下一个数字,要使得该数字最大,输出该数字。
做法:写出一组数据然后枚举情况就能发现,有固定的间隙的一些数字成为一个组合,这些数字的和是必须加上的,只是间隙所在位置不一样,直接暴力枚举就好啦!
代码:
#include
using namespace std;
typedef long long LL;
const int N=4e5+10;
LL a[N],sum[N];
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
a[i+n] = a[i];
}
sum[1] = a[1];
for(int i = 2; i <= n*2; i++) sum[i] = sum[i-2] + a[i];
LL ans = 0;
for(int i = n+1; i <= n*2; i++) ans = max(ans, sum[i]-sum[i-n-1]);
printf("%lld\n", ans);
return 0;
}