CF-284-DIV1-C

题目Array and Operations


直接讲做法,

依次去计算每个素数在整个序列中最多能被约多少次,然后每个素数的约数和就是答案。

计算每个素数约数次数用网络流来做。

假设我们现在计算素数2。

先建立图,图的构成是这样,

编号为奇数的点在左边放一排,编号为偶数的点在右边放一排,

然后对于每个奇数编号点,假设他能约2的次数为k,那么连一条从S(源点)到它的边,流量为k。

对于每个偶数编号的点,假设他能约2的次数为kk,连一条从它到T(汇点)的边,流量为k。

最后对于每个题目中的每个pair,则表示一条从奇数点到偶数点的边,流量为inf。

然后跑出的最大流就是这个素数能取得的最大约数。


下面是代码(网络流部分是网上随意找的代码)

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;

#define FOR(i, j, k) for(int i=(j);i<=(k);i++)
#define REP(i, n) for(int i=0;i<(n);i++)
#define mst(x, y) memset(x, y, sizeof(x));
#define pii pair<int, int>
#define fr first
#define sc second
#define left myleft
#define right myright
#define ll long long
#define ull unsigned long long
#define seed 1331
#define mod ((int)1e9+7)
#define eps 1e-5
#define pdd pair<double, double>

vector <int> ps;
bool vis[300009];
void init(){
    mst(vis, 0);
    for(int i=2;i<=2e5;i++) if(!vis[i])
        for(int j=i+i;j<=2e5;j+=i) vis[j] = 1;
    for(int i=2;i*i<=1e9;i++) if(!vis[i])
        ps.push_back(i);
}

int a[102], n, m, ans = 0;
pii pa[102];



 const int Ni = 210;
 const int MAX = 1<<26;
 struct Edge{
     int u,v,c;
     int next;
 }edge[20*Ni];
 int edn;//边数
 int p[Ni];//父亲
 int d[Ni];
 int sp,tp;//原点,汇点

 void addedge(int u,int v,int c)
 {
     edge[edn].u=u; edge[edn].v=v; edge[edn].c=c;
     edge[edn].next=p[u]; p[u]=edn++;

     edge[edn].u=v; edge[edn].v=u; edge[edn].c=0;
     edge[edn].next=p[v]; p[v]=edn++;
 }
 int bfs()
 {
     queue <int> q;
     memset(d,-1,sizeof(d));
     d[sp]=0;
     q.push(sp);
     while(!q.empty())
     {
         int cur=q.front();
         q.pop();
         for(int i=p[cur];i!=-1;i=edge[i].next)
         {
             int u=edge[i].v;
             if(d[u]==-1 && edge[i].c>0)
             {
                 d[u]=d[cur]+1;
                 q.push(u);
             }
         }
     }
     return d[tp] != -1;
 }
 int dfs(int a,int b)
 {
     int r=0;
     if(a==tp)return b;
     for(int i=p[a];i!=-1 && r<b;i=edge[i].next)
     {
         int u=edge[i].v;
         if(edge[i].c>0 && d[u]==d[a]+1)
         {
             int x=min(edge[i].c,b-r);
             x=dfs(u,x);
             r+=x;
             edge[i].c-=x;
             edge[i^1].c+=x;
         }
     }
     if(!r)d[a]=-2;
     return r;
 }

 int dinic(int sp,int tp)
 {
     int total=0,t;
     while(bfs())
     {
         while(t=dfs(sp,MAX))
         total+=t;
     }
     return total;
 }

void cal(int v){
    FOR(j, 1, n){
        int cnt = 0, x = a[j];
        while(x % v == 0) cnt ++, x /= v;
        if(j&1) addedge(sp, j, cnt);
        else addedge(j, tp, cnt);
    }
    REP(j, m) if(a[pa[j].fr]%v == 0 && a[pa[j].sc]%v == 0){
        if(pa[j].fr & 1) addedge(pa[j].fr, pa[j].sc, 1000000);
        else addedge(pa[j].sc, pa[j].fr, 1000000);
    }
    int tmp = dinic(sp, tp);
    ans += tmp;

    FOR(i, 1, n) while(a[i] % v == 0)
        a[i] /= v;
}

int main(){
//    freopen("in", "r", stdin);

    init();
    cin>>n;
    cin>>m;
    FOR(i,1, n) cin>>a[i];
    REP(i, m) cin>>pa[i].fr>>pa[i].sc;
    REP(i, ps.size()){
        edn = 0;
        sp = 0;
        tp = n+1;
        mst(p, -1);
        mst(edge, -1);

        int v = ps[i];
        cal(v);
    }
    FOR(i, 1, n){
        int v = a[i];
        if(v == 1) continue;

        edn = 0;
        sp = 0;
        tp = n+1;
        mst(p, -1);
        mst(edge, -1);

        cal(v);
    }
    cout<<ans<<endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<div id="wea_rich_text_default_font" style="font-family:微软雅黑;font-size:12;"><p><img alt="" src="/weaver/weaver.file.FileDownload?fileid=aaa9aee4717d33272bd7ea028fa03118b693919f23b18febf9f6cee1158e8f4cf027542c71c8cf98d63770ccdf3bd1750e6b92e28c43dccd4" /></p><div class="ckeditor-html5-video" data-widget="html5video" style="text-align:left"><video controls="controls" src="/weaver/weaver.file.FileDownload?fileid=aad6f413f83191673980c5ee24b412880d6b9e8703caca411faec3276fe8133f5fa7e34630ca89ace63770ccdf3bd175071362141037cfb4e&download=1" style="max-width:100%"> </video></div><table border="1" cellpadding="1" style="width:500px;"> <tbody> <tr> <td style="padding: 1px;">1</td> <td style="padding: 1px;">1</td> </tr> <tr> <td style="padding: 1px;">2</td> <td style="padding: 1px;">2</td> </tr> <tr> <td style="padding: 1px;">3</td> <td style="padding: 1px;">3<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></td> </tr> </tbody></table><p>测试<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></p><p> </p><p>修改一下吧 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq<img alt="" src="/weaver/weaver.file.FileDownload?fileid=a7617945ec5f52ec80aaa43ee8504de0a1b14d5eca4a98834494c85349762c626dec7ba8d0da277106ee600d27743f4e44f710fbddd167603" /></p></div>
最新发布
06-01

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值