标签:比例 close hit ticket algo 优先队列 html pre queue
A. Coffee Break
题意:每天有m小时,你喝咖啡需要花一小时,你想在n个时刻都喝过一次咖啡,老板规定连续喝咖啡的间隔必须是d以上,求最少需要多少天才能喝够n次咖啡,并输出每个时刻第几天喝。
题解:map+优先队列,用map将愿意喝咖啡的时间喝在第几天喝咖啡映射起来,优先队列遍历每个时刻和上一次喝的时间间隔是否大于d,若大于d,表示可以同一天喝,否则就在下一天喝
#include<iostream> #include<algorithm> #include<math.h> #include<string> #include<string.h> #include<vector> #include<utility> #include<map> #include<queue> using namespace std; map<int,int>m; priority_queue<int,vector<int>,greater<int> >p; int a[200005],b[200005]; int main() { int n,t,d; scanf("%d%d%d",&n,&t,&d); for(int i=0;i<n;i++) { scanf("%d",&b[i]); a[i]=b[i]; } sort(a,a+n); m[a[0]]=1;//最小的时间点一定是第一天就可以喝 p.push(a[0]); int cnt=1; for(int i=1;i<n;i++) { int now=p.top(); if(a[i]-now>d) { m[a[i]]=m[now];//可以同一天喝 p.pop(); } else m[a[i]]=++cnt;//只能下一天喝 p.push(a[i]); } printf("%d\n",cnt); for(int i=0;i<n;i++) { if(i==0) printf("%d",m[b[i]]); else printf(" %d",m[b[i]]); } printf("\n"); return 0; }
B
C. Bacteria
题意:碗里有n个细菌,只有重量相同的细菌才可以合并在一起,合并后的细菌为两个细菌之后,为了把碗里的所有细菌合并成一个细菌,问最少还要向碗里增加几个细菌?若最后不能合并成一个细菌,输出-1,否则输出最少要加入的细菌个数
题解:优先队列逐个处理即可
#include<iostream> #include<string> #include<string.h> #include<algorithm> #include<map> #include<queue> #define mx 0x3f3f3f3f #define ll long long using namespace std; ll gcd(ll a, ll b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } ll lcm(ll a, ll b)//最小公倍数 { return a / gcd(a, b) * b; } priority_queue<ll,vector<ll>,greater<ll> > p; int main() { ll n; scanf("%lld",&n); for(int i=0;i<n;i++) { ll temp; scanf("%lld",&temp); p.push(temp); } ll flag=0,cnt=0; while(p.size()!=1) { ll now=p.top(); p.pop(); if(p.size()==1) { if(lcm(now,p.top())!=p.top()) { flag=1; break; } } if(now==p.top()) { now=now+p.top(); p.pop(); p.push(now); } else { cnt++; now=now*2; p.push(now); } } if(flag==1) printf("-1\n"); else printf("%lld\n",cnt); return 0; }
D、
题意:给你nn个数,你要给出不同的组合(a,b)(a,b)使得a∗b=A[i]a∗b=A[i],不能重复,但是(a,b)(a,b)和(b,a)(b,a)不同
题解:按照输入顺序枚举每一个数的因子,枚举到一个因子num[i]之后就退出,同时用vis[]反向标记一下这个数,下一次再次遇到这个数,就从上一次的因子num[i]+1继续枚举
用pair数组保存每一个数的一对因子
#include<iostream> #include<algorithm> #include<math.h> #include<string> #include<string.h> #include<vector> #include<utility> #include<map> using namespace std; int vis[10000005],num[10000005];//vis反向标记,用num保存一个因子 pair<int,int>p[200005]; int a[200005]; int n; int solve() { for(int i=0;i<n;i++) { if(vis[a[i]]==1) { vis[a[i]]=0; p[i].first=a[i]/num[a[i]]; p[i].second=num[a[i]]; continue; } int flag=0; for(int j=num[a[i]]+1;j<=sqrt(a[i]);j++)//对于每个数从最小的因子开始找,找到一对就退出,下一次再次遇到这个数就从num[a[i]]+1开始找因子 { if(a[i]%j==0) { flag=1; num[a[i]]=j;//num只存一个因子即可 if(a[i]/j!=j) vis[a[i]]=1;//反向标记,例如第一次找到一组[1,3],用vis标记[3,1]的存在 p[i].first=j; p[i].second=a[i]/j; break;//对于每个数,找到一对因子就退出 } } if(flag==0) return 0; } return 1; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); num[a[i]]=0;//初始化a[i]的因子为0 } if(solve()) { printf("YES\n"); for(int i=0;i<n;i++) printf("%d %d\n",p[i].first,p[i].second ); } else printf("NO\n"); }
F. Tickets
题意:有n次询问每次询问给一个数x,且x自动补全六位ABCDEF(可以有前导零),一个数的不幸运值=abs((D+E+F)-(A+B+C)),求出每个在这个数之前比自己不幸运值低的数的个数
题解:提前预处理所有数的不幸运值,然后统计比这个不幸运值低的数的个数
#include<iostream> #include<string> #include<string.h> #include<algorithm> #include<map> #define mx 0x3f3f3f3f #define ll long long using namespace std; int a[1000005],cnt[300]; ll gcd(ll a, ll b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } int num(int i) { int x=0, y=0; int xx=0,yy=0; x=i%1000; y=i/1000; while(x) { int temp=x; x=x/10; xx=xx+temp%10; } while(y) { int temp=y; y=y/10; yy=yy+temp%10; } return abs(xx-yy); } int main() { int x; memset(cnt, 0, sizeof(cnt)); for(int i=0; i<1000000; i++) { a[i] = 0; x = num(i); cnt[x]++; for(int j=0; j<x; j++) { a[i]+=cnt[j]; } } int n; scanf("%d", &n); while(n--) { scanf("%d", &x); printf("%d\n", a[x]); } return 0; }
H. Theater Square
题意:有一个矩形,挖掉一个小矩形之后用1*2的方块填充这个矩形,填充不完整的地方(会留有一些1*1)需要将1*2的方块打碎成两块用来填充,问打碎多少块1*2的方块
模拟即可
#include<iostream> #include<string> #include<string.h> #include<algorithm> #include<map> #define mx 0x3f3f3f3f #define ll long long using namespace std; int a[1000005],cnt[300]; ll gcd(ll a, ll b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } int num(int i) { int x=0, y=0; int xx=0,yy=0; x=i%1000; y=i/1000; while(x) { int temp=x; x=x/10; xx=xx+temp%10; } while(y) { int temp=y; y=y/10; yy=yy+temp%10; } return abs(xx-yy); } int main() { int x; memset(cnt, 0, sizeof(cnt)); for(int i=0; i<1000000; i++) { a[i] = 0; x = num(i); cnt[x]++; for(int j=0; j<x; j++) { a[i]+=cnt[j]; } } int n; scanf("%d", &n); while(n--) { scanf("%d", &x); printf("%d\n", a[x]); } return 0; }
I
题意:对一组本来连续的数,现在缺失了几个,问你最少缺失了几个
#include<iostream> #include<string> #include<string.h> #include<algorithm> #define mx 0x3f3f3f3f #define ll long long using namespace std; ll a[1005]; int main() { ll n; scanf("%lld",&n); for(int i=0;i<n;i++) scanf("%lld",&a[i]); sort(a,a+n); int cnt=0; for(int i=1;i<n;i++) cnt=cnt+a[i]-a[i-1]-1; printf("%d\n",cnt); }
J
题意:多少组w、h的比例满足x/y,要求w<=a&&h<=b
题解:将x/y化成最简分数,答案就是min(a/x,b/y);
#include<iostream> #include<string> #include<string.h> #include<algorithm> #define mx 0x3f3f3f3f #define ll long long using namespace std; ll gcd(ll a, ll b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } int main() { ll a,b,x,y,xx; scanf("%lld%lld%lld%lld",&a,&b,&x,&y); xx=gcd(x,y); x=x/xx; y=y/xx; printf("%lld\n",min(a/x,b/y)); }
K
题意:可以将n个数进行区间分割要求每个区间的中位数>=m问最多可以分成多少个区间
题解:先将所有数从小到大排序,找到第一个满足条件的中位数,之后的所有数都满足条件
#include<iostream> #include<string> #include<string.h> #include<algorithm> #include<map> #include<queue> #define mx 0x3f3f3f3f #define ll long long using namespace std; ll gcd(ll a, ll b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } ll lcm(ll a, ll b)//最小公倍数 { return a / gcd(a, b) * b; } priority_queue<ll,vector<ll>,greater<ll> > p; int a[5005]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&a[i]); sort(a,a+n); int len=0,now=0,cnt=0; for(int i=0;i<n;i++) { if(a[i]>=m) break; len++; } for(int i=len;i<n;i++) { if(a[i]>=m&&len==now) { cnt++; cnt=cnt+n-(i+1); break; } else now++; } printf("%d\n",cnt); return 0; }
标签:比例 close hit ticket algo 优先队列 html pre queue
原文地址:https://www.cnblogs.com/-citywall123/p/11337031.html