Codeforces Round #432 (Div. 2) 总结
来源:互联网 发布:淘宝详情页html代码 编辑:程序博客网 时间:2024/05/29 15:54
这场…不仅B被hack少了500+分,最后D题还fst了……好惨啊QAQ..
最终排名:rank488..rating+=1,目前rating=1805…(233怎么说我也加了rating)
A. Arpa and a research in Mexican wave
题意:有n个观众,第一时刻第一个观众站起来,第二时刻第二个观众站起来….第k时刻第k个观众站起来,第k+1时刻第k+1个观众站起来并且第一个观众坐下……第n+1时刻,第n+1-k个观众坐下,直到d+k时刻,第n个观众坐下,求第t时刻站着的人数。
思路&&题解:水题一道..我们只要分为三种情况就行了。第一种为t<=k的情况,这种情况第t秒站起来的人数就是t个人了;第二种为t>=n的情况,此时第t秒站起来的人就是max((n+k-t),0)个;而第三种情况就是t>=k&&t<=n了,这种情况站起来的人就是k个..
代码如下:
#include<bits/stdc++.h>using namespace std;int n,k,t;int main() { cin>>n>>k>>t; if(t<=k) cout<<t<<endl; else if(t>=n) cout<<(n+k)-t<<endl; else cout<<k<<endl; return 0;}
B. Arpa and an exam about geometry
题意:给你三个点的坐标,标为a,b,c三个点,问你能否找到一个点,使得a点绕着这个点旋转可以到b点,b点绕着这个点旋转同样角度可以到c点。
思路&&题解:这题看起来有点麻烦,实际上只用判一下三点不共线且线段ab长度等于线段bc长度就行了(为防止精度误差,可以直接判长度平方)。
P.S.我刚开始写的时候就判了a,b的x,y坐标差是否等于b,c的坐标差。这样的话a(0,0),b(3,4),c(3,9)就可以Hack掉我..
代码如下:
#include<bits/stdc++.h>using namespace std;typedef long long ll;ll x[3],y[3];ll getdis(ll a,ll b,ll c,ll d) { return (a-c)*(a-c)+(b-d)*(b-d);}int main(){ ios::sync_with_stdio(false); for(int i=0;i<3;i++) cin>>x[i]>>y[i]; if(getdis(x[2],y[2],x[1],y[1])==getdis(x[0],y[0],x[1],y[1])&&(x[2]-x[1])*(y[0]-y[1])!=(x[0]-x[1])*(y[2]-y[1])) cout<<"Yes"<<endl; else cout<<"No"<<endl; return 0;}
C. Five Dimensional Points
题意:给你n个五维的点,定义一个点为好点,即该点与其他所有点组成的角均不为锐角。
思路&&题解:题解(1): 因为根据三角形内角和180度的定理,我们可以知道,如果这个点与其中两个点的夹角为直角或钝角,那么另外两个角一定是锐角,所以可以直接去掉那两个点,而要是这个角是锐角的话,可以直接去掉这个角。这样均摊下来是O(n^2)的..(比赛时的思路就是这个)
题解(2):比赛结束后第二天,我看了看别人的题解,发现还有一种更简单的方法..观察二维和三维得到,二维上一个好点的周围至多只有4个点,三维上一个好点的周围至多只有6个点..所以五维上如果存在好点,它周围的点必定不多于10个,所以若n>11,我们可以直接输出0。而小于等于11的话直接n^3暴力就行了..
代码如下(题解1):
#include<bits/stdc++.h>using namespace std;const int maxn=1005;typedef long long ll;ll a[maxn],b[maxn],c[maxn],d[maxn],e[maxn];bool vis[maxn];int n,tot=0;inline ll calc(int i,int j,int k) { int v,w,x,y,z,vv,ww,xx,yy,zz; v=a[i]-a[j]; w=b[i]-b[j]; x=c[i]-c[j]; y=d[i]-d[j]; z=e[i]-e[j]; vv=a[i]-a[k]; ww=b[i]-b[k]; xx=c[i]-c[k]; yy=d[i]-d[k]; zz=e[i]-e[k]; return v*vv+w*ww+x*xx+y*yy+z*zz; }int main() { ios::sync_with_stdio(false); cin>>n; memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i]>>d[i]>>e[i]; for(int i=1;i<=n;i++) { if(vis[i]) continue; for(int j=1;j<=n;j++) { for(int k=j+1;k<=n;k++) { if(i==j||i==k) continue; ll tmp=calc(i,j,k); if(tmp<=0) { vis[j]=1; vis[k]=1; break; } else { vis[i]=1; break; } } if(vis[i]) break; } } for(int i=1;i<=n;i++) if(!vis[i]) tot++; cout<<tot<<endl; if(tot==0) return 0; for(int i=1;i<=n;i++) if(!vis[i]) cout<<i<<" "; cout<<endl; return 0;}
D. Arpa and a list of numbers
题意:给你一个长度为n的数组,你有两个操作:
①将某个数删掉,消耗为x;
②将某个数+1,消耗为y。
这个操作可以对某个数多次使用,而你的目的是让最后n个数的Gcd不为1,求最小消耗。
思路&&题解:我们可以知道Gcd是我们知道,Gcd的结果是素数是最好的,所以我们首先筛出1e6以内的素数。
然后考虑对应数字是删除还是增添。我们考虑X和Y两种操作之间的关系:
①如果X<=Y的话,我们就不用进行Y操作了;
②如果x>y,我们设定tmp=X/Y表示我们最多对一个数进行增添数字的次数,如果超过了这个次数,我们不如将其删除来的划算;
之后只要记录一下前缀和,然后枚举一下Gcd,然后乱搞一下就行了。(具体见我代码)。
P.S.我fst的原因是我特判所有数都是1的时候以为不能全部删光,然后就留了一个一要加一,这样花费有时候不是最优的..
代码如下:
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=500001;const int maxp=2000001;vector<int> prime;int isprime[maxp],num[maxn];ll sum[maxp],sx[maxp];void getprime(){ for(int i=2;i<maxp;i++){ if(isprime[i]==0){ prime.push_back(i); for(int j=i+i;j<maxn;j+=i) isprime[j]=1; } }}ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}int main(){ getprime();// cout<<prime.size()<<endl; int n; ll x,y; cin>>n>>x>>y; ll gc=-1; int ones=0,mx=0; for(int i=1;i<=n;i++) { cin>>num[i]; sum[num[i]]++; mx=max(mx,num[i]); ones+=(num[i]==1); if(gc==-1) gc=num[i]; else gc=gcd(gc,num[i]); } if(ones==n) { ll one=n*1LL*y; ll two=n*1LL*x; cout<<min(one,two)<<endl; return 0; } if(gc>1) { cout<<"0"<<endl; return 0; } for(int i=1;i<=2000000;i++) sx[i]=sx[i-1]+sum[i]*i,sum[i]+=sum[i-1]; int sz=(int)prime.size(); ll ans=1e18,now; for(int z=0;z<sz;z++){ int p=prime[z]; now=0; if(p>mx) break; for(int i=1;i<=(mx/p)+1;i++) { int le=(i-1)*p,ri=i*p,mid=max(le,(int)(ri-(x/y)-1)); ll res=sum[ri]-sum[mid]; now+=(sum[mid]-sum[le])*x+(ri*res-(sx[ri]-sx[mid]))*y; } ans=min(ans,now); } cout<<ans<<endl; return 0;}
E. Arpa and a game with Mojtaba
题意:给你n个数,a1,a2,……,an,两人轮流从中改数,每次选一个素数p和一个正整数k,将a1到an中所有可以被p^k整除的数除p^k。当玩家在他的回合把所有数都变成1后(即下一个玩家不能选择p),该玩家就赢了。
题解:(这题题解来自于http://blog.csdn.net/kele52he/article/details/77864968)。由于p只能是素数,所以我们可以把a1~an全都分解质因数,显然不同的素数之间互不影响,所以说我们只要把每一个素数的SG值算出来然后异或就是答案了。接下来就要解决如何对单个素数求SG值。
首先我们要把a1到an的数组处理成因子只有当前的这个素数的数组。比如2,3,4,6,当p=2的时候,我们就把它处理成2^1,2^0,2^2,2^1,也就是1,0,2,1,因为a1到an中所有可以被p^k整除的数都要除p^k,所以对于因子p的个数相同的数我们是可以视为一个数的。所以当我选2^1的时候,1,0,2,1就变成了0,0,1,0。这两个1的变化在任何时候都是一样的,所以说这两个1可以看作一个1。那么我们可以根据这一点来定义一个state:state的第i位为真,当且仅当当前状态下存在一个数等于p^i。比如:1,0,2,1的state值就等于1+2=3。1,2,2,3,3,5的state值就等于1+2+4+16=23。
而对于每一个state,要从1到它的最大位数枚举k,对于每一个k,大于等于k的位数,都要减k(将a1到an中所有可以被p^k整除的数除p^k),比如1,2,2,3,3,5当k为3的时候后续状态就是1,2,2,0,0,2。
所以(state >> k) | (state&((1 << k-1) - 1))是state的后续状态。
然后这题就可以解出来了,需要注意的是要用map来存SG函数的值。
代码如下:
#include<bits/stdc++.h>using namespace std;const int maxl=100000;typedef map<int,int>::iterator mit;map<int,int> SG,num;int n,x,tmp,ans=0,prime[maxl],tot=0;bool notprime[maxl+1];inline void init() { notprime[1]=1; for(int i=2;i<=maxl;i++) { if(!notprime[i]) prime[++tot]=i; for(int j=1;j<=tot&&i*prime[j]<=maxl;j++) { notprime[i*prime[j]]=1; if(i%prime[j]==0) break; } }}inline int solve(int x) { if(x==0) return 0; if(SG.count(x)) return SG[x]; map<int,int> vis; int p=x,t=0; while(p) { p/=2; t++; } for(int i=1;i<=t;i++) vis[solve((x>>i)|(x&((1<<(i-1))-1)))]=1; for(int i=0;;i++) if(!vis[i]) return SG[x]=i;}int main() { init(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&x); for(int pos=1;prime[pos]*prime[pos]<=x;pos++) { tmp=0; while(x%prime[pos]==0) { x/=prime[pos]; tmp++; } if(tmp!=0) num[prime[pos]]=num[prime[pos]]|(1<<(tmp-1)); } if(x!=1) num[x]|=1; } for(mit it=num.begin();it!=num.end();it++) ans=ans^solve(it->second); if(ans==0) puts("Arpa"); else puts("Mojtaba"); return 0;}
- Codeforces Round #432 (Div. 2) 总结
- Codeforces Round #432 (Div. 2)
- Codeforces Round #432 (Div. 2)
- Codeforces Round #432 (Div. 2)
- Codeforces Round #432 (Div.2)
- Codeforces Round #161 (Div. 2)总结
- Codeforces Round #162 (Div. 2)总结
- Codeforces Round #170 (Div. 2)总结
- Codeforces Round #171 (Div. 2)总结
- Codeforces Round #172 (Div. 2)总结
- Codeforces Round #173 (Div. 2)总结
- Codeforces Round #176 (Div. 2)总结
- Codeforces Round #185 (Div. 2) 总结
- Codeforces Round #187 (Div. 2) 总结
- Codeforces Round #190 (Div. 2) 总结
- Codeforces Round #193 (Div. 2)总结
- Codeforces Round #194 (Div. 2)总结
- Codeforces Round #204 (Div. 2)总结
- SGISTL源码探究-第二级配置器
- 解压.tar.xz结尾的文件
- 1对多业务,数据库水平切分架构一次搞定 | 架构师之路
- 批处理实现文本内容居中显示 -shell
- codeforces 846F Random Query
- Codeforces Round #432 (Div. 2) 总结
- 强力推荐!那些你不能错过的 GitHub 插件和工具
- 在Andorid中使用FFmpeg实现YUV解码为BMP
- 准确率,精确率,召回率以及f1
- NYOJ69
- 《UNIX网络编程 卷2》 笔记: 互斥锁与条件变量
- POJ_1015_Jury Compromise
- leetcode 670. Maximum Swap
- 计算机视觉入门概念