Educational Codeforces Round 77 (Rated for Div. 2)node
A. Heatingios
题意:n组数据,每组数据告诉你有ci个数,他们的和为sumi,求他们平方的和最小是多少。c++
思路:对于每组数据让ci个数尽量的相等。(均值不等式可推)算法
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); long long n; cin>>n; while(n--){ long long c,sum; cin>>c>>sum; long long small_num=sum/c,big_num,ans=0; if(sum%c==0){ ans=small_num*small_num*c; }else{ big_num=small_num+1; long long cont_big=sum%c; long long cont_small=c-cont_big; ans=big_num*big_num*cont_big+small_num*small_num*cont_small; } cout<<ans<<endl; } return 0; }
题意:t组数据,每组数据有两个数a和b,如今有两种操做,①:a=a-x,b=b-2x ②:a=a-2x,b=b-x 每次能够其一进行操做,x可取任意正整数,问可否将a和b同时变为0。spa
思路:先取a为较小数,b为较大数,分类讨论。若b为a的2倍,则能够;若b大于a的2倍,则不能够;若a≤b<2a,考虑先将2个数变得相等(a减去1倍b和a的差,b减去2倍b和a的差),若这个数是3的倍数则能够同时减为0。(相等后分别a-2x,b-x再a-x,b-2x)。3d
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n; cin>>n; while(n--){ long long a,b,num1,num2,cha,sheng; cin>>num1>>num2; a=min(num1,num2);b=max(num1,num2); cha=b-a; bool flag; if(cha==a){ flag=true; }else if(cha>a){ flag=false; }else{ sheng=a-cha; if(sheng%3==0){ flag=true; }else{ flag=false; } } if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
题意:你给栅栏涂色,栅栏标号0、一、2……10100,r倍数的栅栏涂第一种颜色,b倍数的栅栏涂第二种颜色,a和b的公倍数能够任选颜色涂,而后将全部涂色的栅栏取下来,按顺序排在一块儿,若是有k个连续的栅栏涂同一种颜色,你将被国王认为是反叛者并处死,问你可否找出涂色方法让你存活,输出服从(就是有方法活着),或反叛者(没有涂色方法能够存活)。blog
思路:先将两个数处以他们的gcd,保证2数互质或相等,取r为较小数,b为较大数。分类讨论。①:若r等于1,则b-1要小于k才能存活,不然处死。②:若b%r≥2,则b对应的栅栏之间能够放b/r+1个r颜色栅栏,而后对这个结果判断是否小于k便可。例如(b=8,r=3的某一段):排序
(补充,2个数a和b互质,则必定存在k使得 (k×a)%b=t,t能够为小于b的任意值)。若是b%r<2,则b对应的栅栏之间能够放b/r个r颜色栅栏,对这个结果判断是否小于k便可。
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t; long long r,b,k,num1,num2; cin>>t; while(t--){ cin>>num1>>num2>>k; r=min(num1,num2); b=max(num1,num2); long long gcd_num=__gcd(r,b); r/=gcd_num;b/=gcd_num; bool flag=true; if(r==1){ if(b>=k+1) flag=false; else flag=true; }else{ if(b%r>=2){ if(b/r+1>=k){ flag=false; }else{ flag=true; } }else{ if(b/r>=k){ flag=false; }else{ flag=true; } } } if(flag) cout<<"OBEY"<<endl; else cout<<"REBEL"<<endl; } return 0; }
题意:一个数轴,你从0出发要到n+1,你有m个士兵能够选(每一个士兵有一个敏捷度),而后有k个陷阱和时间t。每一个陷阱有三个值l,r,d,l是陷阱位置 ,r是解除陷阱你须要去的位置,d是危险程度。士兵的敏捷度若小于d则士兵当即死亡。有以下几种操做。
· 若是你在x,你能够耗时1秒去到x-1或x+1
· 若是你和你的军队同时在x,你能够耗时1秒带着你的士兵去到x-1或x+1,若去到的地方有陷阱且会让你的士兵被杀,则你不能这么移动。
· 若是你到达了x,且x是解除陷阱的位置(x为某个r),则x对应的陷阱当即解除,不耗费时间。
如今问在时间t内你最多能够带多少个士兵到达目的地。
思路:首先贪心的思想,你若带K个士兵则必定是敏捷度最大的K个士兵,因此二分搜索士兵的个数,并判断相应个数的士兵可否在时间t内到达。
对于可否到达,将陷阱按照l从小到大的顺序排序,危险值小于等于当前选的K个士兵中敏捷度最小的陷阱能够忽略。对于每一个陷阱,若拆除对应的最远的r大于后面陷阱的位置l,则后面的陷阱与以前的陷阱一块儿拆除,并更新最远的r。若拆除对应的最远r小于下一个陷阱l,则把以前选中的陷阱拆除后带着部队来到l-1.算法全部便可。
#include<bits/stdc++.h> using namespace std; map<int,int>tree; struct node{ int agility,num; }now_node; struct node_point{ int l,r,d; }now_point; vector<node>soldier; vector<node_point>point; bool judge(int x,int t,int aim){ int max_point=0,last_move=0,sum=0; for(int i=0;i<point.size();i++){ if(x>=point[i].d) continue; if(max_point>=point[i].l){ max_point=max(point[i].r,max_point); }else{ sum+=(max_point-last_move)*2+(point[i].l-1-last_move); max_point=point[i].r; last_move=point[i].l-1; } } sum+=(max_point-last_move)*2+(aim-last_move); if(sum<=t) return true; else return false; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n,m,t,k,get_num; cin>>m>>n>>k>>t; for(int i=1;i<=m;i++){ cin>>get_num; if(tree.find(get_num)==tree.end()){ tree[get_num]=1; }else{ tree[get_num]++; } } for(auto i=tree.begin();i!=tree.end();i++){ now_node.agility=(*i).first; now_node.num=(*i).second; soldier.push_back(now_node); } for(int i=1;i<=k;i++){ cin>>now_point.l>>now_point.r>>now_point.d; point.push_back(now_point); } sort(point.begin(),point.end(),[](const node_point &a,const node_point &b){return a.l<b.l;}); int l=0,r=soldier.size(); while(l<r){ int mid=(l+r)/2; if(judge(soldier[mid].agility,t,n+1)){ r=mid; }else{ l=mid+1; } } int ans=0; if(l==soldier.size()){ cout<<ans<<endl; }else{ for(int i=l;i<soldier.size();i++){ ans+=soldier[i].num; } cout<<ans<<endl; } return 0; }