问题虫洞——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;
}