FBI_一起来玩呀3—— [B-C-D]

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章