Codeforces Round #284 (Div. 1) C. Array and Operations 二分图匹配

因为只有奇偶之间有操作, 可以看出是二分图, 然后拆质因子, 二分图最大匹配求答案就好啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std;

const int N = 5000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;

int odd[N], even[N], ocnt, ecnt;
int L[N], R[N];
int G[N][N];
int match[N];
bool vis[N];
int n, m;

int path(int u) {
    for(int v = 1; v <= ecnt; v++) {
        if(G[u][v] && !vis[v]) {
            vis[v] = true;
            if(match[v] == -1 || path(match[v])) {
                match[v] = u;
                return 1;
            }
        }
    }
    return 0;
}

int main() {
    memset(match, -1, sizeof(match));
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        int x;
        scanf("%d", &x);
        if(i & 1) {
            L[i] = ocnt + 1;
            for(int j = 2; j * j <= x; j++) {
                if(x % j) continue;
                while(x % j == 0) {
                    odd[++ocnt] = j;
                    x /= j;
                }
            }
            if(x > 1) odd[++ocnt] = x;
            R[i] = ocnt;
        } else {
            L[i] = ecnt + 1;
            for(int j = 2; j * j <= x; j++) {
                if(x % j) continue;
                while(x % j == 0) {
                    even[++ecnt] = j;
                    x /= j;
                }
            }
            if(x > 1) even[++ecnt] = x;
            R[i] = ecnt;
        }
    }
    while(m--) {
        int u, v; scanf("%d%d", &u, &v);
        if(v & 1) swap(u, v);
        for(int i = L[u]; i <= R[u]; i++)
            for(int j = L[v]; j <= R[v]; j++)
                if(odd[i] == even[j]) G[i][j] = 1;
    }
    int ans = 0;
    for(int i = 1; i <= ocnt; i++) {
        memset(vis, false, sizeof(vis));
        if(path(i)) ans++;
    }
    printf("%d\n", ans);
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/10351267.html

时间: 2024-08-21 12:44:36

Codeforces Round #284 (Div. 1) C. Array and Operations 二分图匹配的相关文章

Codeforces Round #284 (Div. 2) b

/**  * @brief Codeforces Round #284 (Div. 2) b  * @file b.cpp  * @author mianma  * @created 2014/12/26 11:51  * @edited  2014/12/18 11:51  * @type brute  * @note  */ #include <fstream> #include <iostream> #include <string> #include <c

Codeforces Round #284 (Div. 1)

A. Crazy Town 这一题只需要考虑是否经过所给的线,如果起点和终点都在其中一条线的一侧,那么很明显从起点走点终点是不需要穿过这条线的,否则则一定要经过这条线,并且步数+1.用叉积判断即可. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<string> 5 #include<map> 6 #define N 100010 7 #def

[Codeforces Round #284 (Div. 1) B]Name That Tune(概率Dp)

Description It turns out that you are a great fan of rock band AC/PE. Peter learned that and started the following game: he plays the first song of the list of n songs of the group, and you have to find out the name of the song. After you tell the so

Codeforces Round #284 (Div. 2) C题(计算几何)解题报告

题目地址 简要题意: 给出两个点的坐标,以及一些一般直线方程Ax+B+C=0的A.B.C,这些直线作为街道,求从一点走到另一点需要跨越的街道数.(两点都不在街道上) 思路分析: 从一点到另一点必须要跨的街道等价于两点一点在这条直线一侧,另一条在另一侧.只需要将两点坐标带进去,一正一负即可.将这些直线依次检验,统计总和. 1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream> 4 using

Codeforces Round #284 (Div. 2) A

解题思路:给出 n个电影的精彩时段(a[i],b[i]),和每次可以跳过的时间x,问要看完所有的精彩时刻,至少需要看多长时间的电影. 因为要时间最少,所有除了精彩时刻的电影则能跳过就跳过(用取余来算),不能跳过则加到耗费的总时间里面. 反思:WA两次是因为没有搞清楚物理上的时刻和时间的关系, -------------------------------------------------- 1    2     3     4      5      6       7       8 如果我

Codeforces Round #284 (Div. 2)

Problem C 题目大意:一个平面内有一些无限长的直线,把平面分成了若干块,从一块走一步可以走到与它有公共边的另一块,但是只有公共点不能一步走过去.给定两个在块内部的点,问从S点到T点最少走几步. 题目分析:由于每步只能跨越公共边,不能从两直线交点处跨越,所以一步只能越过 S 与 T 之间的一条直线,那么答案就是 S 与 T 之间有多少条直线(即 S 与 T 在这些直线的两侧).判断 S 与 T 在直线 l 两侧 :  l : ax + by + c = 0        (a*Sx + b

Codeforces Round #284 (Div.1) Solution

A 有意思,初看觉得怎么A还要求线交还这么麻烦.仔细一想.每次只能过一条线.如果有一条线在两点间,则必须过它们.在同侧的线不需要过.于是就简单了. B 时限好紧,我用了一个诡异的方法的时间复杂也是O(nT)却超了. C 奇数和偶数显然形成了二分图.对每一个素因子来一次最大流. D 首先注意到模LCM的60,噢.由于之前那个题,一下就想到分块大法好.什么嘛,明明就可以线段树呀.

Codeforces Round #284 (Div. 1) A. Crazy Town 计算几何

题面 题意:给你2个点A和B,和n条直线(ax+by+c=0),给n个a,b,c,求A到B至少跨过多少条直线 题解:对于每条直线,看2个点是否在他同侧,异侧答案就+1 1 #include<bits/stdc++.h> 2 using namespace std; 3 double x1,x2,y11,y2,a,b,c,t1,t2; 4 int n,ans; 5 int main() 6 { 7 cin>>x1>>y11; 8 cin>>x2>>

Codeforces Round #311 (Div. 2) D. Vitaly and Cycle(二分图染色,奇环)

给定n个点,m条边. 求最少最要加几条边使图中存在奇环,且输出此时加边的方法种数 根据题意,只可能为 0:已经存在奇环,dfs搜到已经染色的且颜色相同 1:判断每个连通块里的 染色黑白色的个数 2 :某个点的 度 > 1 3:0条边 1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include<vector> 5 #include<stack> 6 #include