bzoj4514 [Sdoi2016]数字配对
2017-12-28 15:49
441 查看
(http://www.elijahqi.win/2017/12/28/bzoj4514-sdoi2016%E6%95%B0%E5%AD%97%E9%85%8D%E5%AF%B9/)
Description
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
Input
第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
Output
一行一个数,最多进行多少次配对
Sample Input
3
2 4 8
2 200 7
-1 -2 1
Sample Output
4
HINT
n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5
这题 还是一个 要是看出 以分解质因数之后质因数的个数的奇偶性来划分的话 就是板子题了
可惜我看不出qwq
确实 因为 我只有一种可能就是我质因数个数 奇数和偶数才可以构成答案 所以不妨我把质因数个数位奇数的放在左边 偶数的放在右边 然后每个点 连容量位b[i]的点去源或者汇 然后如果这两个数 满足条件的话 则连上他们中间的c数组相乘作为费用的边 跑最大费用流即可 注意判断是否是质数的时候我一开始以为我既然都求出了not_prime这个数组了 那就直接用吧 不行,显然是错的啊 我有可能数超过了1e5 就gg了 所以还是循环一下 看能否分解质因数判断是否是质数 注意本题long long十分重要
Description
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
Input
第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
Output
一行一个数,最多进行多少次配对
Sample Input
3
2 4 8
2 200 7
-1 -2 1
Sample Output
4
HINT
n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5
这题 还是一个 要是看出 以分解质因数之后质因数的个数的奇偶性来划分的话 就是板子题了
可惜我看不出qwq
确实 因为 我只有一种可能就是我质因数个数 奇数和偶数才可以构成答案 所以不妨我把质因数个数位奇数的放在左边 偶数的放在右边 然后每个点 连容量位b[i]的点去源或者汇 然后如果这两个数 满足条件的话 则连上他们中间的c数组相乘作为费用的边 跑最大费用流即可 注意判断是否是质数的时候我一开始以为我既然都求出了not_prime这个数组了 那就直接用吧 不行,显然是错的啊 我有可能数超过了1e5 就gg了 所以还是循环一下 看能否分解质因数判断是否是质数 注意本题long long十分重要
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define M 440000 #define N 22000 #define inf 1LL<<60 #define ll long long using namespace std; inline char gc(){ static char now[1<<16],*T,*S; if (T==S) {T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();} return x*f; } int tot,prime[110000],q1[220],q2[220],tot1,tot2,T,h[220],flag[220];ll f[220]; bool not_prime[110000];int path[220],pre[220],num=1,n,a[220],b[220],c[220]; struct node{ int x,y,z,next;ll c; }data[55000]; inline void insert1(int x,int y,int z,ll c){ data[++num].y=y;data[num].z=z;data[num].next=h[x];h[x]=num;data[num].c=c;data[num].x=x; data[++num].y=x;data[num].z=0;data[num].next=h[y];h[y]=num;data[num].c=-c;data[num].x=y; } inline bool spfa(){ for (int i=0;i<=n+1;++i) f[i]=-inf; memset(flag,0,sizeof(flag));queue<int>q;q.push(0);memset(pre,-1,sizeof(pre));f[0]=0;flag[0]=1; while(!q.empty()){ int x=q.front();q.pop();flag[x]=0; for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z;ll c=data[i].c; if (f[x]+c>f[y]&&z){ f[y]=f[x]+c;pre[y]=x;path[y]=i; if (!flag[y]) flag[y]=1,q.push(y); } } }if (pre[T]==-1) return 0;else return 1; } inline bool judge(int i,int j){ if (!a[i]||!a[j]||a[i]%a[j]&&a[j]%a[i]) return 0; int dis=max(a[j]/a[i],a[i]/a[j]); for (int i=1;i<=tot;++i) if (prime[i]>=dis) break;else if (dis%prime[i]==0)return 0;return 1; } int main(){ freopen("bzoj4514.in","r",stdin); n=read();for (int i=1;i<=n;++i) a[i]=read();T=n+1;not_prime[0]=1;not_prime[1]=1; for (int i=1;i<=n;++i) b[i]=read();for (int i=1;i<=n;++i) c[i]=read(); for (int i=2;i<=1e5;++i){ if (!not_prime[i]) prime[++tot]=i; for (int j=1;prime[j]*i<=1e5;++j) { not_prime[prime[j]*i]=1;if (i%prime[j]==0) break; } } for (int i=1;i<=n;++i){ int sum=0,now=a[i]; for (int j=1;j<=tot;++j){ while(now%prime[j]==0) sum++,now/=prime[j];if (now==1) break; } if (sum%2) q1[++tot1]=i;else q2[++tot2]=i; } for (int i=1;i<=tot1;++i) for (int j=1;j<=tot2;++j) if (judge(q1[i],q2[j])) insert1(q1[i],q2[j],0x3f3f3f3f,(ll)c[q1[i]]*c[q2[j]]); for (int i=1;i<=tot1;++i) insert1(0,q1[i],b[q1[i]],0);ll ans1=0; for (int i=1;i<=tot2;++i) insert1(q2[i],T,b[q2[i]],0);int ans=0; //for (int i=2;i<=num;++i) printf("%d %d %d %d\n",data[i].x,data[i].y,data[i].z,data[i].c); while(spfa()){ int minn=0x3f3f3f3f,now=T;ll tmp=0; while(now) minn=min(minn,data[path[now]].z),now=pre[now];now=T; while(now) {tmp+=data[path[now]].c;data[path[now]].z-=minn;data[path[now]^1].z+=minn;now=pre[now];} if (ans1+tmp*minn<0){ ans-=ans1/tmp;break; }else ans+=minn,ans1+=tmp*minn; } printf("%d",ans); return 0; }
相关文章推荐
- BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)
- bzoj4514: [Sdoi2016]数字配对(费用流)
- [BZOJ4514][Sdoi2016]数字配对(数学+费用流)
- BZOJ 4514 [Sdoi2016]数字配对
- 【bzoj4514】[Sdoi2016]数字配对 费用流
- 【BZOJ】4514: [Sdoi2016]数字配对
- [二分图 费用流] BZOJ 4514 [Sdoi2016]数字配对
- [bzoj4514] [Sdoi2016]数字配对
- bzoj4514 [Sdoi2016]数字配对
- 【BZOJ 4514】[Sdoi2016]数字配对 费用流
- 费用流 【SDOI2016】 bzoj4514 数字配对
- 图论(费用流):BZOJ 4514 [Sdoi2016]数字配对
- BZOJ 4514: [Sdoi2016]数字配对(费用流)
- [bzoj4514][SDOI2016]数字配对——二分图
- AC日记——[Sdoi2016]数字配对 bzoj 4514
- [Bzoj4514][Sdoi2016]数字配对(费用流)
- BZOJ 4514: [Sdoi2016]数字配对
- bzoj 4514: [Sdoi2016]数字配对(二分图+费用最大流)
- [bzoj4514] [Sdoi2016]数字配对
- [BZOJ4514] [SDOI2016] 数字配对 - 费用流