• 1874 素数和最大



    题目描述 Description

        有一天萌萌哒Sevenkplus在跟素数们玩>_<。。。他玩着玩着突然想到一个问题!就是这样的:
        从1到n这n个自然数中,选出一些数使得它们之间两两互质并且它们的和最大。
        当然Sevenkplus几分钟就秒杀了>_<。。。你也来试试吧~~~
        比如说n=10,那么选择{1,5,7,8,9}就行了,答案是30。

    输入描述 Input Description

        一行一个整数n

    输出描述 Output Description

        一行一个整数表示答案

    样例输入 Sample Input

        3

    样例输出 Sample Output

        6

    数据范围及提示 Data Size & Hint

        【数据范围】

        测试点
        1..2:n<=100
        3..5:n<=1000
        6..10:n<=200000

         

        【卖萌向】

        素数可是很可爱的哦^_^

         

        【来源】

        我们都爱GYZ摸你赛 Problem C Hard

    好题

    一开始眼瞎+脑残,以为肯定是每一个素数都单独选它的最大次幂,全WA

    好吧,看题解,果真是网络流+数论

    先筛素数,把素数分成两类,一类是小于等于根号n的,这些可以自己乘多次,大于根号n的只能有一次幂

    我们考虑这两类凑成一对一对的,如果凑成一对会更优,就连一条权值为增益的边(不过为什么不能小素数凑对呢?)

    然后做二分图最大匹配

    代码就别看了,因为建图,我的变量名已经乱了

      1 var
      2     flag:array[0..200010]of boolean;
      3     zhi,best:array[0..100000]of longint;
      4     first,next,last,val,cost,vis,db,link:array[0..200010]of longint;
      5     n,tot,jie,num,time:longint;
      6     ans:int64;
      7 
      8 procedure shai;
      9 var
     10     i,j:longint;
     11 begin
     12     for i:=2 to n do
     13       begin
     14         if flag[i]=false then
     15         begin
     16           inc(tot);
     17           zhi[tot]:=i;
     18         end;
     19         for j:=1 to tot do
     20           begin
     21             if i*zhi[j]<=n then flag[i*zhi[j]]:=true
     22             else break;
     23             if i mod zhi[j]=0 then break;
     24           end;
     25       end;
     26 end;
     27 
     28 procedure insert(x,y,z:longint);
     29 begin
     30     inc(num);
     31     last[num]:=y;
     32     next[num]:=first[x];
     33     first[x]:=num;
     34     val[num]:=z;
     35     if db[x]<z then db[x]:=z;
     36 end;
     37 
     38 procedure init;
     39 var
     40     i,j,k,s:longint;
     41 begin
     42     read(n);
     43     shai;
     44     ans:=1;
     45     for i:=1 to tot do
     46       begin
     47         k:=zhi[i];
     48         while k*zhi[i]<=n do
     49           k:=k*zhi[i];
     50         if k>zhi[i] then jie:=i;
     51         best[i]:=k;
     52         ans:=ans+k;
     53       end;
     54     for i:=1 to jie do
     55       for j:=jie+1 to tot do
     56         begin
     57           s:=zhi[j];
     58           while s*zhi[i]<=n do
     59             s:=s*zhi[i];
     60           if s>best[i]+best[j] then insert(i,j,s-best[i]-best[j]);
     61         end;
     62     for i:=1 to jie do
     63       insert(i,tot+i,0);
     64 end;
     65 
     66 function find(x:longint):boolean;
     67 var
     68     i:longint;
     69 begin
     70     vis[x]:=time;
     71     i:=first[x];
     72     while i<>0 do
     73       begin
     74         if (vis[last[i]]<>time)and(val[i]=db[x]+db[last[i]]) then
     75         begin
     76           vis[last[i]]:=time;
     77           if (link[last[i]]=0)or(find(link[last[i]])) then
     78           begin
     79             link[last[i]]:=x;
     80             cost[last[i]]:=val[i];
     81             exit(true);
     82           end;
     83         end;
     84         i:=next[i];
     85       end;
     86     exit(false);
     87 end;
     88 
     89 function km:int64;
     90 var
     91     i,j,k,d:longint;
     92 begin
     93     for i:=1 to jie do
     94       begin
     95         while true do
     96           begin
     97             inc(time);
     98             if find(i) then break;
     99             d:=maxlongint;
    100             for k:=1 to jie do
    101               if vis[k]=time then
    102               begin
    103                 j:=first[k];
    104                 while j<>0 do
    105                   begin
    106                     if vis[last[j]]<>time then
    107                     if d>db[k]+db[last[j]]-val[j] then d:=db[k]+db[last[j]]-val[j];
    108                     j:=next[j];
    109                   end;
    110               end;
    111             if d=maxlongint then break;
    112             for j:=1 to jie do
    113               if vis[j]=time then dec(db[j],d);
    114             for j:=jie+1 to tot do
    115               if vis[j]=time then inc(db[j],d);
    116           end;
    117       end;
    118     km:=0;
    119     for i:=jie+1 to tot do
    120       inc(km,cost[i]);
    121 end;
    122 
    123 begin
    124     init;
    125     write(km+ans);
    126 end.
    View Code
  • 相关阅读:
    生活有时候就是个戏本
    Android dp、dpi、px
    iOS10以后相机、相册等授权问题
    iOS圆角性能问题
    激荡10年,珍贵的毕业礼物
    Android API 指南
    Android 配置
    Android Error
    安卓 MIUI真机测试
    iOS 同一段文字显示不同颜色
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3599938.html
Copyright © 2020-2023  润新知