A . A r r a y B a l a n c i n g A.\ Array\ Balancing A. Array Balancing
题意:
可以选择 i i i通过交换 a i , b i a_i,b_i ai,bi使相邻元素之间的差值之和最小。
这题猜了好长时间思路一直不对,但是其实很好想,运用宏观思维的话,因为这是两个序列,那肯定是小的和小的放在一起,大的与大的放在一起呀,
当然这样可能不太严谨,不过这只是个 A A A题QAQ
\令人头秃
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 60;
int a[N],b[N];
int n;
void solve()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++) cin >> b[i];
for(int i=1;i<=n;i++){
if(a[i]>b[i]) swap(a[i],b[i]);
}
int res=0;
for(int i=1;i<n;i++){
res+=abs(a[i]-a[i+1]);
res+=abs(b[i]-b[i+1]);
}
cout << res << endl;
}
signed main(){
int t; cin >> t;
while(t--) solve();
return 0;
}
当然这里面的第一种方法我是没看懂的,但是第二种看起来很简单,那就是一对一对地比较交换前后的变化,如果交换之后绝对值之和变小了那就交换,就这样遍历完两个序列。
(感觉还是挺暴力的,我甚至马上排除了这种做法。。。)
B . G e t t i n g Z e r o B.\ Getting\ Zero B. Getting Zero
(这道题目好有趣!*…*)
又是一道有关位运算的题目!一生之敌!!!、
但是不得不说位运算真的很奇妙!但也很令人(我)头秃!
这道题目:
首先我们可以发现题目给的模数非常特别!我没发现QAQ
众所周知
32768
32768
32768是
2
2
2的
15
15
15次方,对这个数取模就很怪(?)
32768 = ( 1000 0000 0000 0000 ) B 32768=(1000\ 0000\ 0000\ 0000)_B 32768=(1000 0000 0000 0000)B
当我们把给定的数都用二进制表示:
19 = ( 10011 ) B 19=(10011)_B 19=(10011)B 此时如果我们将他加 1 1 1,那么直观的,它变成了 20 20 20,不直观地,但也挺直观的,它变成了 ( 10100 ) B (10100)_B (10100)B,如果此时我们将他右移 15 − 2 = 13 15-2=13 15−2=13位,那么他将会以 1000 0000 0000 0000 1000\ 0000\ 0000\ 0000 1000 0000 0000 0000结尾,也就是说他能被这个数整除了,那取模就是 0 0 0了。
就是这么个思路,但是具体要加多少个 1 1 1和左移多少位合适,是要枚举一下的。
当然要看清数据范围, n n n取不到 0 0 0,但! a a a可以取到,睁开眼睛啊!
但是 0 0 0要特判一下,上述写法 0 0 0过不了QAQ(因为WA了)
还有 r e s res res记得每次都要更新。
#include <bits/stdc++.h>
using namespace std;
int a;
signed main(){
int n,res=20; cin >> n;
while(n--)
{
res=20;
cin >> a;
if(a==0){
cout << 0 << ' ';
continue;
}
for(int i=0;i<=15;i++)
{
int add=i,cnt0=0;
for(int j=0;j<=15;j++){
if(((a+add)>>j)&1) break;//右移直到最低位是1就结束,这样结束的时候cnt0记录的是最低位的0地数量(也就是不再需要左移的位数)
cnt0++;
}
res=min(res,add+15-cnt0);//加1的操作数与需要左移的操作数
}
cout << res << ' ';
}
return 0;
}
其实代码中的记录 0 0 0的数量那一步想用 l o w b i t lowbit lowbit来实现来着,感觉本质上差不多,但是暂时还没想要怎么写,先写过再说。。。