20170612测试

Posted SummerSky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 helper.js(20170612)

20170612

20170612xlVBA含方框文档填表

20170612xlVBA多文件多类别分类求和匹配

20170612-20170616第六周

[20170612]FOR ALL COLUMNS SIZE repeat(11g).txt