問題蟲洞——B:B - Make Product Equal One
黑洞內窺:
給出一個n個數的序列, 你每次可以花費 1 money 使得序列中的某個數+1或-1.
求讓序列的乘積之和爲1的最小花費。
思維光年:
-1要成對出現,1就不用管,0可以算做一個-1或1
暴力就好了啦!!!
ACcode:
#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//將近int類型最大數的一半,而且乘2不會爆int
#define MOD 1000000007 // MOD%4 = 3
const double pi = acos(-1.0);
const double eps = 1e-6;
int a[MAXN];
int main()
{
int n, ans=0, cnt=0, tem=0;
ll sum=0;
cin >> n;
for(int i=0; i<n; ++i)
scanf("%d", &a[i]);
//sort(a, a+n);
for(int i=0; i<n; ++i)
{
if(a[i] == 0)
{
sum++;
ans++;
}
else if(a[i] < -1 || a[i] == -1)
{
cnt++;
sum+=(-1 - a[i]);
}
else if(a[i] > 1)
{
tem++; //其實這裏沒用。。。
sum+=(a[i] - 1);
}
}
//ans = ans+cnt;
if(ans > 0 || cnt%2 == 0)
cout << sum << '\n';
else
cout << sum+2 << '\n';
return 0;
}
問題蟲洞——C: C - Almost Equal
黑洞內窺:
輸入n,給出1~2n的數,將這2n個數圍成一個圈,
使得每n個數之間的和兩兩不能相差超過1.
若無這樣的序列,輸出NO
有則輸出YES,且輸出這樣的一個序列。
思維光年:
根據樣例,猜出偶數時爲NO,奇數時爲YES
然後肯定是有規律的,推出來就是。。
將數字這樣放,然後先全部輸出上面的再全部輸出下面的,,就是答案了;
ACcode:
#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//將近int類型最大數的一半,而且乘2不會爆int
#define MOD 1000000007 // MOD%4 = 3
const double pi = acos(-1.0);
const double eps = 1e-6;
int a[MAXN], b[MAXN];
int main()
{
int n;
cin >> n;
if(n%2 == 0) puts("NO");
else {
puts("YES");
int c = 2, d = 1, ans = 0;
a[1] = 1;
for(int i=2; i<=2*n-1; ++i)
{
if(ans < 2)
{
b[d] = i;
d++;
ans++;
}
else if(ans < 4)
{
a[c] = i;
c++;
ans++;
}
if(ans == 4)
ans = 0;
}
b[n] = 2*n;
for(int i=1; i<=n; ++i)
cout << a[i] << ' ';
for(int i=1; i<=n; ++i)
{
cout << b[i];
if(i!=n) cout << ' ';
else cout << '\n';
}
}
return 0;
}
問題蟲洞——D:D - Shortest Cycle CodeForces - 1206D
黑洞內窺:
給出n個數,如果如果i!=j且(a[i]&a[j])!=0,則在i與j之間建邊
求圖的最小環 (無向圖最小環至少三個頂點)
思維光年:
(我讀題的時候還在納悶爲什麼2不可以。。。。) 還是太菜
理性的求解:
如果二進制位的某一位爲1的數的數量>=3那麼答案就是3(因爲這樣就證明了至少有三個點有邊)
如果都不爲3,則不爲0的數最多隻有2*63=126個(long long只有63位有效)
所以如果不爲0的數大於126個答案就是3了。。。因爲每一位上都有1.
否則直接用Floyd暴力最小環就行了;
ACcode:
#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 200
#define INF 300//將近int類型最大數的一半,而且乘2不會爆int
#define MOD 1000000007 // MOD%4 = 3
const double pi = acos(-1.0);
const double eps = 1e-6;
ll a[100005];
int g[MAXN][MAXN], d[MAXN][MAXN], ans=INF;
int main()
{
int n, tot=0;
cin >> n;
for(int i=1; i<=n; ++i)
{
ll x;
scanf("%lld", &x); //0不重要。因爲0不可能和任何點建邊。
if(x) a[++tot] = x;
}
if(tot > 63*3) puts("3");
else
{
for(int i=1; i<=tot; ++i) //建圖
for(int j=1; j<=tot; ++j)
if(a[i]&a[j])
g[i][j]=g[j][i]=d[i][j]=d[j][i]=1;
else
g[i][j]=g[j][i]=d[i][j]=d[j][i]=INF;
for(int k=1; k<=tot; ++k) //Floyd求最小環
{
for(int i=1; i<=k-1; i++)
for(int j=i+1; j<=k-1; j++)
ans = min(ans, d[i][j]+g[i][k]+g[k][j]);
for(int i=1; i<=tot; ++i)
for(int j=1; j<=tot; ++j)
d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
}
if(ans == INF) puts("-1");
else printf("%d\n", ans);
}
return 0;
}