BZOJ 3308 九月的咖啡店 费用流
2015-05-14 20:18
288 查看
题目大意:在[1,n][1,n]区间内选择一些数,使得这些数两两互质,求这些数的和的最大值
容易发现对于一个最优解,每个质数存在且仅存在于一个数中。(废话。
但是有可能一个数中存在多个质数
下面是两个结论:
1.一个数中最多存在两个不同的质数
2.这两个质数一个<n√<\sqrt n,一个>n√>\sqrt n
我完全不会证明这两个结论,这两个结论都是官方题解里的
然后就好办了,我们对于<n√<\sqrt n的质数和>n√>\sqrt n的质数建立二分图,求最大费用最大流即可
但是这样会T掉,因为图太大了
因此我们有两个剪枝:
1.对于>n2>\frac n2的质数,一定单独存在于解集中,不用扔进二分图跑了
2.如果某两个质数组合起来不如分别取最大后加起来,就不加这条边
加了之后基本就能过了……20W的点跑了9s+
这个题是PE的355 听说PE的那群人跑的都是模拟退火?
据说巨快……
容易发现对于一个最优解,每个质数存在且仅存在于一个数中。(废话。
但是有可能一个数中存在多个质数
下面是两个结论:
1.一个数中最多存在两个不同的质数
2.这两个质数一个<n√<\sqrt n,一个>n√>\sqrt n
我完全不会证明这两个结论,这两个结论都是官方题解里的
然后就好办了,我们对于<n√<\sqrt n的质数和>n√>\sqrt n的质数建立二分图,求最大费用最大流即可
但是这样会T掉,因为图太大了
因此我们有两个剪枝:
1.对于>n2>\frac n2的质数,一定单独存在于解集中,不用扔进二分图跑了
2.如果某两个质数组合起来不如分别取最大后加起来,就不加这条边
加了之后基本就能过了……20W的点跑了9s+
这个题是PE的355 听说PE的那群人跑的都是模拟退火?
据说巨快……
[code]#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 10100 #define S 0 #define T (M-1) #define INF 0x3f3f3f3f using namespace std; int n; long long ans; int prime[M<<2],tot; bool not_prime[200200]; namespace Max_Cost_Max_Flow{ struct abcd{ int to,flow,cost,next; }table[100100]; int head[M],tot=1; void Add(int x,int y,int f,int c) { table[++tot].to=y; table[tot].flow=f; table[tot].cost=c; table[tot].next=head[x]; head[x]=tot; } void Link(int x,int y,int f,int c) { Add(x,y,f,c); Add(y,x,0,-c); } bool Edmonds_Karp() { static int q[65540],cost[M],from[M]; static unsigned short r,h; static bool v[M]; int i; memset(cost,0xef,sizeof cost); cost[S]=0;q[++r]=S; while(r!=h) { int x=q[++h];v[x]=false; for(i=head[x];i;i=table[i].next) if(table[i].flow&&cost[table[i].to]<cost[x]+table[i].cost) { cost[table[i].to]=cost[x]+table[i].cost; from[table[i].to]=i; if(!v[table[i].to]) v[table[i].to]=true,q[++r]=table[i].to; } } if(cost[T]<0) return false; ans+=cost[T]; for(i=from[T];i;i=from[table[i^1].to]) table[i].flow--,table[i^1].flow++; return true; } } void Linear_Shaker() { int i,j; for(i=2;i<=n;i++) { if(!not_prime[i]) prime[++tot]=i; for(j=1;prime[j]*i<=n;j++) { not_prime[prime[j]*i]=true; if(i%prime[j]==0) break; } } } int Get_Max(int n,int x) { int re=1; while(n>=x) n/=x,re*=x; return re; } int main() { int i,j; cin>>n; Linear_Shaker(); for(i=1;i<=tot&&prime[i]*2<=n;i++) if((long long)prime[i]*prime[i]<=n) { Max_Cost_Max_Flow::Link(S,i,1,0); Max_Cost_Max_Flow::Link(i,T,1,Get_Max(n,prime[i])); } else { Max_Cost_Max_Flow::Link(i,T,1,0); Max_Cost_Max_Flow::Link(S,i,1,prime[i]); } for(;i<=tot;i++) ans+=prime[i]; for(i=1;i<=tot&&(long long)prime[i]*prime[i]<=n;i++); for(;i<=tot&&prime[i]*2<=n;i++) for(j=1;j<=tot&&(long long)prime[j]*prime[j]<=n;j++) { if(prime[i]*prime[j]>n) break; int temp=Get_Max(n/prime[i],prime[j])*prime[i]; if(temp>Get_Max(n,prime[j])+prime[i]) Max_Cost_Max_Flow::Link(j,i,1,temp); } while( Max_Cost_Max_Flow::Edmonds_Karp() ); cout<<ans+1<<endl; return 0; }
相关文章推荐
- 【BZOJ 3308】 3308: 九月的咖啡店 (费用流|二分图最大权匹配)
- bzoj 3308: 九月的咖啡店【最大费用最大流】
- 【BZOJ-3308】九月的咖啡店 最大费用最大流 + 线性筛素数
- bzoj 3308: 九月的咖啡店(最大费用最大流)
- 【bzoj3308】九月的咖啡店 费用流
- bzoj 3308: 九月的咖啡店 (费用流)
- bzoj 3308: 九月的咖啡店 费用流
- bzoj3308: 九月的咖啡店 数学 玄学 最大流
- BZOJ3308 九月的咖啡店
- 【bzoj3130】【SDOI2013】【费用流】【最大流】
- BZOJ 3876 AHOI2014 支线剧情 费用流
- BZOJ 1070 修车 费用流(拆点)
- BZOJ-2324 营救皮卡丘 最小费用可行流+拆下界+Floyd预处理
- BZOJ.4819.[SDOI2017]新生舞会(01分数规划 费用流SPFA)
- [BZOJ4819][SDOI2017]新生舞会(分数规划+费用流,KM)
- [ZJOI2010][bzoj1834] 网络扩容 [费用流]
- [HAOI2010][bzoj2424] 订货 [费用流]
- BZOJ 2879 [Noi2012]美食节 | 费用流 动态开点
- BZOJ 2424 DP OR 费用流
- 【bzoj3442】学习小组 费用流