zoukankan      html  css  js  c++  java
  • 20170612测试

    问题 A: 装果子

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 96  解决: 54

    题目描述

    果园里有n颗果树,每棵果树都有一个编号i(1≤in)。小明已经把每棵果树上的果子都摘下来堆在了这棵树的下方,每棵树下方的果子体积为ai

    现在小明将拿来m个袋子把这些果子都装进袋子里。每个袋子的体积为v。小明会按照如下规则把果子装进袋子里:

    (a)从第1棵果树开始装起,由1到n一直装到第n棵果树。

    (b)如果这棵果树下的果子能全部装进当前这个袋子,就装进去;如果不能,就关上当前这个袋子,打开一个新的袋子开始装。

    小明希望在能把所有果子都装进袋子里的前提下,v尽量小。m个袋子并不一定都要装进果子。

    输入

    输入文件名为fruit.in

    输入第1行,包含两个整数nm

    第2行,包含n个整数ai

    输出

    输出文件名为fruit.out

    输出仅1行,表示最小的v

    样例输入

    fruit.in
    3 3
    1 2 3
    fruit.out
    3
    fruit.in
    5 3
    1 3 6 1 7
    fruit.out
    7
    fruit.in
    6 3
    1 2 1 3 1 4
    fruit.out
    4

    样例输出

    【输入输出样例解释1】 每个袋子的体积为3即可。前2棵果树的果子装在第一个袋子里,第3棵果树的果子装在第二个袋子里。第三个袋子不用装了。 【输入输出样例解释2】 每个袋子的体积为7即可。前2棵果树的果子装在第一个袋子里,此时第一个袋子已经装了4单位体积的果子,第3棵果树的果子装不下了,所以装进第二个袋子里,第4棵果树的果子刚好装进第二个袋子,第5棵果树的果子装进第三个袋子里。 【输入输出样例解释3】 每个袋子的体积为4即可。前3棵果树的果子装在第一个袋子里,第4~5棵果树的果子装在第二个袋子里,第6棵果树的果子装在第三个袋子里。

    提示

    【数据范围】


    对于40%的数据,0<mn≤1,000,0<ai≤1,000;


    对于70%的数据,0<mn≤100,000,0<ai≤100,000;


    对于100%的数据,0<mn≤100,000,0<ai≤1,000,000,000。

    裸裸的二分:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define ll long long
     5 using namespace std;
     6 int a[100005];
     7 int n,m; 
     8 bool check(ll x){
     9     ll v=x; int nu=1;
    10     for (int i=1;i<=n;i++)
    11         if (v>=(ll)a[i]) v-=(ll)a[i];
    12         else v=x-(ll)a[i],nu++;
    13     if (nu<=m) return 1;
    14     return 0;
    15 }
    16 int main(){
    17     ll sum=0,Max=0;
    18     scanf("%d%d",&n,&m);
    19     for (int i=1;i<=n;i++){
    20         scanf("%d",&a[i]);
    21         sum+=(ll)a[i];
    22         Max=max(Max,(ll)a[i]);
    23     }
    24     ll l=Max,r=sum;
    25     while (l<r){
    26         ll mid=(l+r)>>1;
    27         if (check(mid)) r=mid;
    28         else l=mid+1;
    29     }
    30     printf("%lld",l);
    31     return 0;
    32 }
    View Code

    问题 B: 零件加工

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 107  解决: 46

    题目描述

    工匠小K最近有n个零件需要加工。每个零件都需要ti天的时间来完成,每个零件每延迟一天加工都要缴纳一定的罚金si。延迟的天数为从今天算起到该工作开始的那天,第一个零件加工没有罚金。现在小K想知道怎样安排加工顺序可以使他要交的罚金最少,最少是多少。

    这个数可能会很大,请输出这个数对m取模后的结果。

    输入

    输入文件名为process.in

    输入第一行为一个整数n,表示需要加工的零件总数。

    第二行为一个整数m,表示答案要对m取模。

    第3~n+2行,每行两个整数tisi

    输出

    输出文件名为process.out

    输出仅一行,一个整数,表示小K最少要缴纳的罚金对m取模的结果。

    样例输入

    process.in
    2
    100
    2 33
    33 2
    process.out
    4
    process.in
    4
    100
    3 3
    6 4
    2 2
    8 5
    process.out
    81

    样例输出

    【输入输出样例解释1】 先加工第一个,需要2天时间,再加工第二个。需要缴纳的罚金为2×2=4。 【输入输出样例解释2】 如果按照1→2→3→4的顺序进行加工,需要缴纳的罚金为0×3+3×4+(3+6)×2+ (3+6+2)×5=85; 最佳方案是3→1→2→4,此时需要缴纳的罚金为0×2+2×3+(2+3)×4+(2+3+6)×5=81。

    提示

    【数据范围】

    对于40%的数据,0<n≤10,000,0<ti,si≤10,000; 

    对于80%的数据,0<n≤100,000,0<ti,si≤2×10^9,0<m≤10^8; 

    对于100%的数据,0<n≤100,000,0<ti,si≤2×10^9,0<m≤10^18。

     贪心,按照t/s升序排序然后计算。 

    解题关键是以状态下相邻两个的选择。

    详细证明见HK

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll mul(ll a,ll b,ll pp){ll ans=0;for(;b;b>>=1,a=mo(a+a,pp))if(b&1)ans=mo(ans+a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 #define N 100005
    38 struct node{
    39     ll t,s;
    40 }f[N];
    41 bool cmp(node a,node b){
    42     return b.s*a.t<a.s*b.t;
    43 }
    44 int main()
    45 {
    46     int n=read(); ll m=read(),sum=0,ans=0;
    47     for (int i=1;i<=n;i++) f[i].t=read(),f[i].s=read();
    48     sort(f+1,f+n+1,cmp);
    49     for (int i=1;i<=n;i++){
    50         ans=mo(ans+mul(f[i].s,sum,m),m);
    51         sum=mo(sum+f[i].t,m);
    52     }
    53     printf("%lld",mo(ans,m));
    54     return 0;
    55 }
    View Code

    问题 C: 种树

    时间限制: 2 Sec  内存限制: 128 MB

    题目描述

    为了绿化乡村,H村积极响应号召,开始种树了。

    H村里有n幢房屋,这些屋子的排列顺序很有特点,在一条直线上。于是方便起见,我们给它们标上1~n。树就种在房子前面的空地上。

    同时,村民们向村长提出了m个意见,每个意见都是按如下格式:希望第li个房子到第ri个房子的房前至少有ci棵树。

    因为每个房屋前的空地面积有限,所以每个房屋前最多只能种ki棵树。

    村长希望在满足村民全部要求的同时,种最少的树以节约资金。请你帮助村长。

    输入

    输入文件名为tree.in

    输入第1行,包含两个整数nm

    第2行,有n个整数ki

    第2~m+1行,每行三个整数lirici

    输出

    输出文件名为tree.out

    输出1个整数表示在满足村民全部要求的情况下最少要种的树。村民提的要求是可以全部满足的。

    样例输入

    tree.in
    5 3
    1 1 1 1 1
    1 3 2
    2 4 2
    4 5 1
    tree.out
    3
    tree.in
    4 3
    3 2 4 1
    1 2 4
    2 3 5
    2 4 6
    tree.out
    8

    样例输出

    【输入输出样例解释1】 如图是满足样例的其中一种方案,最少要种3棵树。 【输入输出样例解释2】 如图是满足样例的其中两种方案,左图的方案需要种9棵树,右图的方案需要种8棵树。可以验证,最少需要种8棵树。

    提示

    【数据范围】


    对于30%的数据,0<n≤100,0<m≤100,ki=1;


    对于50%的数据,0<n≤2,000,0<m≤5,000,0<ki≤100;


    对于70%的数据,0<n≤50,000,0<m≤100,000,0<ki≤1,000;


    对于100%的数据,0<n≤500,000,0<m≤500,000,0<ki≤5,000

    法一差分约束:

    开一个s数组记录前缀和。 
    根据题意我们可以得到3个约束条件: 
    s[r]-s[l-1]≥c,① 
    s[i]≥s[i-1],② 
    s[i]-s[i-1]≤k,③ 
    根据①得s[l]-s[r]≤-c,在r和l-1之间连一条权值为-c的边。 
    根据②得s[i-1]-s[i]≤0,在i和i-1之间连一条权值为0的边。 
    根据③在i-1和i之间连一条权值为k的边。 
    50分算法:Bellman-Ford。 
    时间复杂度:O(nm) 
    70分算法:SPFA。 
    时间复杂度:O(km) 
    100分算法: 
    观察到最大可能需要连150w条边,因此我们要考虑有些边是否需要连。 
    我们可以只根据条件①计算,每次更新后O(n)检查是否满足条件②和③,如果不满足就修改,这样只用连50w条边,可以过全部数据。 
    Tip:事实上SPFA可以过100%

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<ll,ll> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 ld eps=1e-9;
    25 ll pp=1000000007;
    26 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    27 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    28 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    31 ll read(){ ll ans=0; char last=' ',ch=getchar();
    32 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    34 if(last=='-')ans=-ans; return ans;
    35 }
    36 #define N 500005
    37 #include<queue>
    38 const ll inf=1e15;
    39 vector<pr> vec[N];
    40 ll dis[N];
    41 bool v[N];
    42 void spfa(int x){
    43     for (int i=0;i<N;i++) dis[i]=inf,v[i]=0;
    44     dis[x]=0; v[x]=1;
    45     queue<int> q; q.push(x);
    46     while (!q.empty()){
    47         int u=q.front(); q.pop(); v[u]=0;
    48         for (int i=0;i<vec[u].size();i++){
    49             int v_=vec[u][i].fi,c=vec[u][i].sc; 
    50             if (dis[v_]>dis[u]+c){
    51                 dis[v_]=dis[u]+c;
    52                 if (!v[v_]) q.push(v_),v[v_]=1;
    53             }
    54         }
    55     }
    56 }
    57 int main(){
    58     int n=read(),m=read();
    59     for (int i=1;i<=n;i++){
    60         int k=read();
    61         vec[i-1].pb(mp(i,k));
    62         vec[i].pb(mp(i-1,0));
    63     }
    64     for (int i=1;i<=m;i++){
    65         int a=read(),b=read(),c=read();
    66         vec[b].pb(mp(a-1,-c));
    67     }
    68     spfa(n);
    69     printf("%lld",-dis[0]);
    70     return 0;
    71 } 
    View Code

    法二贪心:

    题目中要求要种树种得少,就要使一棵树给多个区间使用,这样,尽量在重叠区间种树即可,而重叠位置一定是区间尾部。处理问题时,先按所有区间的结束位置排序,若结束位置相同,则按开始位置从大到小排序。之后依次处理每个区间,先在第一个区间尾部种满足要求的树,对下一个区间,看差多少棵就在该区间尾部种多少。 
    【算法步骤】: 
    1.先快排 
    2.对每个区间依次处理 
    a.从前到后扫描这个区间,统计点的个数; 
    b.若点的个数超过了要求的点数,则continue; 
    c.从该区间后向前扫描,添加覆盖点。 
    3.输出ans 
    Tip:这种方法只适用于小数据,对于大数据我们可以用树状数组加快求和,即过程a,还可以用并查集的方法来加速种树过程c,当有一段区间的树种满时把它与前一个区间合并就行了。

    还是考虑一下 (FROM Lhq)

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 #define N 500000
    38 #define lowbit(i) (i&(-i))
    39 struct node{
    40     int a,b; ll v;
    41 }f[N+5];
    42 ll T[N+5],k[N+5],fl[N+5]; ll ans;
    43 void add(int a,int b){
    44     for (int i=a;i<=N;i+=lowbit(i)) T[i]+=b;
    45 }
    46 ll sum(int a){
    47     ll Sum=0;
    48     for (int i=a;i>0;i-=lowbit(i)) Sum+=T[i];
    49     return Sum;
    50 }
    51 bool cmp(node a,node b){
    52     return a.b<b.b||a.b==b.b&&a.a<a.b;
    53 }
    54 int main(){
    55     int n=read(),m=read();
    56     for (int i=1;i<=n;i++) k[i]=read();
    57     for (int i=1;i<=m;i++) {
    58         f[i].a=read(); f[i].b=read(); f[i].v=read(); 
    59     }
    60     sort(f+1,f+m+1,cmp);
    61     for (int i=1;i<=m;i++){
    62         ll Sum=sum(f[i].b)-sum(f[i].a-1);
    63         if (f[i].v>Sum){
    64             int j=f[i].b; 
    65             while (Sum<f[i].v){
    66                 if (fl[j]>0) j=fl[j]; 
    67                 if (f[i].v>=Sum+k[j]){
    68                     Sum+=k[j]; ans+=k[j]; add(j,k[j]); k[j]=0; j--; 
    69                 } else {
    70                     ans+=f[i].v-Sum; add(j,f[i].v-Sum); k[j]-=f[i].v-Sum; Sum=f[i].v;
    71                 }
    72             }
    73             fl[f[i].b]=j;
    74         }
    75         //cout<<i<<" "<<ans<<endl;
    76     } 
    77     printf("%lld",ans);
    78     return 0;
    79 }
    View Code

    问题 D: 完全平方数

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 74  解决: 36

    题目描述

    一个数如果是另一个整数的完全平方,那么我们就称这个数为完全平方数(Pefect Sqaure),也称平方数。

    小A认为所有的平方数都是很perfect的~

    于是他给了小B一个任务:用任意个不大于n的不同的正整数相乘得到完全平方数,并且小A希望这个平方数越大越好。

    请你帮助小B告诉小A满足题意的最大的完全平方数。

    输入

    输入文件名为number.in 

     

    输入仅 1行,一个数n

     

    输出

    输出文件名为number.out

    输出仅1行,一个数表示答案。由于答案可以很大,所以请输出答案对100000007取模后的结果。

    样例输入

    【输入输出样例1】
    number.in
    7
    number.out
    144
    【输入输出样例解释1】
    144=2×3×4×6,是12的完全平方。

    样例输出

    【输入输出样例2】
    number.in
    9
    number.out
    5184
    【输入输出样例解释2】
    5184=3×4×6×8×9,是72的完全平方。

    提示

    【数据范围】


    对于20%的数据,0<n≤100;


    对于50%的数据,0<n≤5,000;


    对于70%的数据,0<n≤100,000;


    对于100%的数据,0<n≤5,000,000。

     数的阶乘中所有质因数的幂数整除2*2;

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int pp=100000007;
     6 #define ll long long
     7 long long Ans=1LL;
     8 #define N 5000005
     9 int pr[N],f[N];
    10 ll q(ll a,ll b){
    11     ll ans=1LL; for (;b;b>>=1,a=(a*a)%pp) if (b&1) ans=(ans*a)%pp; return ans;
    12 }
    13 int main(){ 
    14     int n,nu=0; scanf("%d",&n);
    15     for (int i=2;i<=n;i++){
    16         if (!f[i]) pr[++nu]=i;
    17         for (int j=1;j<=nu && pr[j]*i<=n;j++){
    18             f[pr[j]*i]=1;
    19             if (i%pr[j]==0) break;
    20         }  
    21     }
    22     for (int i=1;i<=nu;i++){
    23         ll x=(ll)pr[i],ans=0LL;
    24         while (x<=(ll)n){
    25             ans+=((ll)n/x);
    26             x*=(ll)pr[i];
    27         }
    28         Ans=(Ans*q((ll)pr[i],ans>>1))%pp;
    29     }
    30     printf("%lld",q(Ans,2));
    31     return 0;
    32 }
    View Code

    问题 E: 卡片游戏

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 50  解决: 21

    题目描述

    小D举办了元旦联欢活动,其中有一个卡片游戏。

    游戏的规则是这样的:有n张卡片,每张卡片上正面写着一个小于等于100的正整数ai,反面都是一样的花色。这n张卡片正面朝下叠成一堆,玩这个游戏的人从中可以抽出连续的k(1≤kn)张卡片。如果对于这k张卡片上的数字的平均值a,满足l<=a<=r,那他就可以获得小礼物一件。

    小W来玩这个游戏了,她事先通过某些途径知道了这n张卡片上写的数字,现在她想知道她获得小礼物的期望值。

    小W对小数很头疼,所以请你用分数的形式告诉她答案。

    输入

    输入文件名为game.in

    输入第1行,三个整数nlr

    第2行,包含n个整数ai

    输出

    输出文件名为game.out

    输出仅1行,表示小W获得小礼物的期望值。输出格式为“P/Q”(PQ互质)。如果期望值是01就不用输出分数了

    样例输入

    game.in
    4 2 3
    3 1 2 4
    game.out
    7/10

    样例输出

    【输入输出样例2】
    game.in
    4 1 4
    3 1 2 4
    game.out
    1

    提示

    【输入输出样例解释1】



    【输入输出样例解释1】抽出的卡片


    a(保留2位小数)


    是否满足l<=a<=r



    3


    3.00




    1


    1.00


    2


    2.00




    4


    4.00


    3,1


    2.00




    1,2


    1.50


    2,4


    3.00




    3,1,2


    2.00




    1,2,4


    2.33




    3,1,2,4


    2.50




     【输入输出样例解释2】


    由上表得,小W总是可以获得小礼物。因此期望值是1


     


    【数据范围】


    对于30%的数据,0<n≤10,000;


    对于70%的数据,0<n≤100,000;


    对于100%的数据,0<n≤500,000,0<l<r≤100。


    由表可得,一共有10种情况,其中有7种情况小W可以获得小礼物。因此小W获得小礼物的期望值是7/10。

     数学推:

    T2-1 
    T2-2

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 #define N 500005
    38 ll gcd(ll a,ll b){
    39     return (b==0)?a:gcd(b,a%b); 
    40 }
    41 ll cnta,cntb;
    42 int a[N],b[N],c[N],sum[N]; 
    43 void mega(int l,int r){
    44     int mid=(l+r)>>1,i=l,j=mid+1,k=0;
    45     while (i<=mid && j<=r){
    46         while (a[i]<a[j] && i<=mid){
    47             c[++k]=a[i]; i++;
    48         }
    49         while(a[i]>=a[j] && j<=r){
    50             c[++k]=a[j]; j++; cnta+=(ll)(mid-i+1); 
    51         }
    52     } 
    53     while (i<=mid) c[++k]=a[i],i++;
    54     while (j<=r) c[++k]=a[j],j++; 
    55     for (int i=1;i<=k;i++)
    56         a[i+l-1]=c[i];
    57 }
    58 void megb(int l,int r){
    59     int mid=(l+r)>>1,i=l,j=mid+1,k=0;
    60     while (i<=mid && j<=r){
    61         while (b[i]<=b[j] && i<=mid){
    62             c[++k]=b[i]; i++;
    63         }
    64         while(b[i]>b[j] && j<=r){
    65             c[++k]=b[j]; j++; cntb+=(ll)(mid-i+1); 
    66         }
    67     } 
    68     while (i<=mid) c[++k]=b[i],i++;
    69     while (j<=r) c[++k]=b[j],j++; 
    70     for (int i=1;i<=k;i++)
    71         b[i+l-1]=c[i];
    72 }
    73 void msort(int l,int r){
    74     if (l==r) return;
    75     int mid=(l+r)>>1;
    76     msort(l,mid);
    77     msort(mid+1,r);
    78     mega(l,r);
    79     megb(l,r);
    80 }
    81 int main(){
    82     int n=read(),l=read(),r=read(); 
    83     for (int i=1;i<=n;i++) {
    84         int a_=read();
    85         sum[i]=sum[i-1]+a_;
    86         a[i]=l*i-sum[i];
    87         b[i]=r*i-sum[i];
    88     }
    89     msort(0,n);
    90     ll B=(ll)n*((ll)n+1LL)/2LL;
    91     ll A=cnta-cntb;
    92     ll C=gcd(A,B);
    93     if (A==0) printf("0");
    94     else if (A==B) printf("1"); 
    95     else printf("%lld/%lld",A/C,B/C);
    96     return 0;
    97 }
    View Code

    问题 F: 围栏问题

    时间限制: 2 Sec  内存限制: 128 MB
    提交: 43  解决: 23

    题目描述

    在一片草原上,有n只兔子无忧无虑地生活着。这片草原可以划分成m×m的方阵。每个方格内最多有一只兔子。

    一位饲养员负责喂养这些兔子。为了方便,她需要用篱笆建造最多k座围栏,将草原上的兔子全部围起来。

    围栏需要满足以下条件:

    (1)必须沿着网格线建造;

    (2)每座围栏是一个不与自身重叠或相交的封闭回路;

    (3)各座围栏之间互相不重叠、不相交;

    (4)一座围栏不能被围在另一座围栏里面。

    请你帮助饲养员计算一下围栏总长度的最小值。

    输入

    输入文件名为fence.in

    输入第1行为三个整数mkn

    接下来n行每行为一对正整数xy,表示第x行第y列的方格中有一只兔子。

    输出

    输出文件名为fence.out

    输出仅1行,为一个正整数,表示围栏总长度的最小值。

    样例输入

    【输入输出样例1】
    fence.in
    6 1 4
    1 3
    4 2
    4 4
    6 4
    fence.out
    18

    样例输出

    【输入输出样例2】
    fence.in
    6 2 4
    1 3
    4 2
    4 4
    6 4
    fence.out
    16

    提示

    【数据范围】


    对于10%的数据,k=1;


    对于10%~30%的数据,k=2;


    对于30%~60%的数据,n≤10;


    对于100%的数据,1≤k≤n≤16,m≤1,000。

    首先,两个围栏互相包含的情况不可能在最优解中出现(把里面那个拆掉可以节省篱笆,得到一个更优解)。 
    其次,两个围栏相交的情况也一定不是最优,如下图所示,把重叠的部分拆掉可以得到更优解。 
    T3-1 
    由于我们的目标是最小化周长,可以得到这样一条重要性质:矩形的围栏比不规则形状的更优。如图,把里面的边往外平移,成为一个矩形的边框,这样可以在周长不变的情况下,围住更多的土地。(不用担心扩展出去的部分会和另外的围栏相交,因为这不可能在最优解中出现,刚才已经提到) 
    T3-2 
    有些情况下,矩形边框不仅扩大围住的范围而且能节省周长。 
    T3-3 
    所以,接下来我们只需考虑用矩形去包围兔子就够了。 
    T3-4 
    定义基本矩形或叫极小矩形——假如这个矩形再往里缩小一点就会有兔子从里面逃出。 
    T3-5 
    如就不是一个极小矩形,它可以往里收缩

    现在它是一个极小矩形。 
    容易发现,最优解中必然只包含极小矩形。 


    解法一: 
    搜索+剪枝,枚举每一个兔子所在的栅栏,如果还可以再多一种栅栏就可以多一种选择:即开一个刚刚包围自己的栅栏。另一种选择就是和之前的某一个集合的兔子合并放到一个栅栏里,计算周长时找到上下左右的最大差值,记得+1。

    解法二: 
    我们可以预处理出所有极小矩形:枚举所有兔子的非空子集,找出这个子集中最上、最左、最右、最下的兔子,就可得到一个极小矩形。(当然这样计算会出现许多重复的,剔除即可)。这种做法虽然是指数级的但是编码简单,而且n很小,仍可接受。 
    现在我们有了一堆矩形,对于每个矩形我们掌握它的两个属性:周长、围住了的兔子集合。问题转化为:从这堆矩形中选出不超过k个,在满足这些兔子集合互不相交,且其并集恰好是兔子全集的条件下,最小化总周长。 
    这是一个典型的精确覆盖问题,搜索解决即可。可以使用二进制来表示各个集合,用位运算的方法达到优化的效果。也可以用DLX来做,更快,更爽。 

    只有解法一,法二不会(┭┮﹏┭┮):

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 const int N=20;
    38 int x[N],y[N],n,m,k;
    39 int lx[N],ly[N],rx[N],ry[N],ans=1e09;
    40 void dfs(int x_,int y_,int z)
    41 {
    42     if(z>ans) return;
    43     if(x_>n) { ans=z; return; }
    44     if(y_<k){
    45         rx[y_+1]=lx[y_+1]=x[x_]; ry[y_+1]=ly[y_+1]=y[x_];
    46         dfs(x_+1,y_+1,z+4);
    47         rx[y_+1]=lx[y_+1]=0; ry[y_+1]=ly[y_+1]=0;
    48     }
    49     int ax,ay,bx,by,nz;
    50     for(int i=1;i<=y_;i++)
    51     {
    52         ax=lx[i]; ay=ly[i];
    53         bx=rx[i]; by=ry[i];
    54         nz=z-2*((bx-ax+1)+(by-ay+1));
    55         lx[i]=min(x[x_],lx[i]); rx[i]=max(x[x_],rx[i]);
    56         ly[i]=min(y[x_],ly[i]); ry[i]=max(y[x_],ry[i]);
    57         nz+=2*((rx[i]-lx[i]+1)+(ry[i]-ly[i]+1));
    58         dfs(x_+1,y_,nz);
    59         lx[i]=ax; ly[i]=ay;
    60         rx[i]=bx; ry[i]=by;
    61     }
    62 }
    63 int main()
    64 {
    65     m=read(),k=read(),n=read();
    66     for(int i=1;i<=n;i++) x[i]=read(),y[i]=read();
    67     dfs(1,0,0);
    68     printf("%d
    ",ans);
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    MySQL全文索引--转载
    提升接口tps
    数据库连接池了解和常用连接池对比
    SpringBoot跨域配置,解决跨域上传文件
    oss上传
    MySQL高级 之 explain
    spring cloud集群负载均衡
    Xmind日常操作
    产品经理应该懂点经济学
    初谈产品
  • 原文地址:https://www.cnblogs.com/SXia/p/7123301.html
Copyright © 2011-2022 走看看