20170612测试
Posted SummerSky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20170612测试相关的知识,希望对你有一定的参考价值。
问题 A: 装果子
时间限制: 1 Sec 内存限制: 128 MB提交: 96 解决: 54
题目描述
果园里有n颗果树,每棵果树都有一个编号i(1≤i≤n)。小明已经把每棵果树上的果子都摘下来堆在了这棵树的下方,每棵树下方的果子体积为ai。
现在小明将拿来m个袋子把这些果子都装进袋子里。每个袋子的体积为v。小明会按照如下规则把果子装进袋子里:
(a)从第1棵果树开始装起,由1到n一直装到第n棵果树。
(b)如果这棵果树下的果子能全部装进当前这个袋子,就装进去;如果不能,就关上当前这个袋子,打开一个新的袋子开始装。
小明希望在能把所有果子都装进袋子里的前提下,v尽量小。m个袋子并不一定都要装进果子。
输入
输入文件名为fruit.in
输入第1行,包含两个整数n和m。
第2行,包含n个整数ai。
输出
输出文件名为fruit.out
输出仅1行,表示最小的v。
样例输入
样例输出
提示
【数据范围】
对于40%的数据,0<m≤n≤1,000,0<ai≤1,000;
对于70%的数据,0<m≤n≤100,000,0<ai≤100,000;
对于100%的数据,0<m≤n≤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 }
问题 B: 零件加工
时间限制: 1 Sec 内存限制: 128 MB提交: 107 解决: 46
题目描述
工匠小K最近有n个零件需要加工。每个零件都需要ti天的时间来完成,每个零件每延迟一天加工都要缴纳一定的罚金si。延迟的天数为从今天算起到该工作开始的那天,第一个零件加工没有罚金。现在小K想知道怎样安排加工顺序可以使他要交的罚金最少,最少是多少。
这个数可能会很大,请输出这个数对m取模后的结果。
输入
输入文件名为process.in。
输入第一行为一个整数n,表示需要加工的零件总数。
第二行为一个整数m,表示答案要对m取模。
第3~n+2行,每行两个整数ti和si。
输出
输出文件名为process.out。
输出仅一行,一个整数,表示小K最少要缴纳的罚金对m取模的结果。
样例输入
样例输出
提示
贪心,按照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 }
问题 C: 种树
时间限制: 2 Sec 内存限制: 128 MB题目描述
为了绿化乡村,H村积极响应号召,开始种树了。
H村里有n幢房屋,这些屋子的排列顺序很有特点,在一条直线上。于是方便起见,我们给它们标上1~n。树就种在房子前面的空地上。
同时,村民们向村长提出了m个意见,每个意见都是按如下格式:希望第li个房子到第ri个房子的房前至少有ci棵树。
因为每个房屋前的空地面积有限,所以每个房屋前最多只能种ki棵树。
村长希望在满足村民全部要求的同时,种最少的树以节约资金。请你帮助村长。
输入
输入文件名为tree.in
输入第1行,包含两个整数n,m。
第2行,有n个整数ki。
第2~m+1行,每行三个整数li,ri,ci。
输出
输出文件名为tree.out
输出1个整数表示在满足村民全部要求的情况下最少要种的树。村民提的要求是可以全部满足的。
样例输入
样例输出
提示
【数据范围】
对于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 }
法二贪心:
题目中要求要种树种得少,就要使一棵树给多个区间使用,这样,尽量在重叠区间种树即可,而重叠位置一定是区间尾部。处理问题时,先按所有区间的结束位置排序,若结束位置相同,则按开始位置从大到小排序。之后依次处理每个区间,先在第一个区间尾部种满足要求的树,对下一个区间,看差多少棵就在该区间尾部种多少。
【算法步骤】:
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 }
问题 D: 完全平方数
时间限制: 1 Sec 内存限制: 128 MB提交: 74 解决: 36
题目描述
一个数如果是另一个整数的完全平方,那么我们就称这个数为完全平方数(Pefect Sqaure),也称平方数。
小A认为所有的平方数都是很perfect的~
于是他给了小B一个任务:用任意个不大于n的不同的正整数相乘得到完全平方数,并且小A希望这个平方数越大越好。
请你帮助小B告诉小A满足题意的最大的完全平方数。
输入
输入文件名为number.in
输入仅 1行,一个数n。
输出
输出文件名为number.out
输出仅1行,一个数表示答案。由于答案可以很大,所以请输出答案对100000007取模后的结果。
样例输入
样例输出
提示
【数据范围】
对于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)