兰州大学第一届『飞马杯』程序设计竞赛(同步赛)
Posted PdrEam
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了兰州大学第一届『飞马杯』程序设计竞赛(同步赛)相关的知识,希望对你有一定的参考价值。
https://ac.nowcoder.com/acm/contest/16520#question
A★★比赛新机制★★
环形取数,取n个 可以正取也可以逆取,第一个取的贡献n次,第二个n-1,第n个1次。
长的很像前缀和,然后递推一下,每次算上新的,利用前缀和改一下。
逆取直接sum*(n+1)-正取就好
int a[N],sum[N],n; void solve(){ cin>>n; int m=2*n,mm=3*n; for(int i=1;i<=n;++i){ cin>>a[i]; a[i+n]=a[i];a[i+2*n]=a[i]; } for(int i=1;i<=mm;++i){ sum[i]=sum[i-1]+a[i]; } int ans=inf,now=0,tmp=n; for(int i=n+1;i>=2;--i){ now=now+a[i]*tmp;tmp--; } //cout<<"=="<<now<<endl; ans=min(ans,now); ans=min(ans,(sum[n+1]-sum[1])*(n+1)-now); for(int i=n+2;i<=m;++i){ now=now+a[i]*n; now=now-(sum[i-1]-sum[i-n-1]); ans=min(ans,now); ans=min(ans,(sum[i]-sum[i-n])*(n+1)-now); //cout<<"=="<<now<<endl; } cout<<ans<<endl; }
★★生命的游戏★★
很明显是模拟,然后模拟就好,注意下确定一个周期是跟初始状态比较的
如果一个死亡的的细胞周围恰好有 333 个活的细胞,那么下一个回合时,这个细胞的状态将转为“生”
如果一个存活的的细胞周围活细胞的数量大于 333 或小于 222,那么下一个回合时,这个细胞的状态将转为“死”
其他情况下,细胞的存活状态不变
const int N= 1e2+7; int a[N][N][N],ans,n,k; int dd(int x,int y){ int f=1; for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ if(a[i][j][x]!=a[i][j][y]){ f=0;break; } } } return f; } int pd(int i,int j,int now){//死了判活 int cnt=0; int l=j-1,r=j+1,up=i-1,dw=i+1; if(l==0)l=n; if(r==n+1)r=1; if(up==0)up=n; if(dw==n+1) dw=1; if(a[i][l][now]==1) cnt++; if(a[i][r][now]==1) cnt++; if(a[up][l][now]==1) cnt++; if(a[up][j][now]==1) cnt++; if(a[up][r][now]==1) cnt++; if(a[dw][l][now]==1) cnt++; if(a[dw][j][now]==1) cnt++; if(a[dw][r][now]==1) cnt++; if(cnt==3) return 1; return 0; } int pd2(int i,int j,int now){//活了判死 int cnt=0; int l=j-1,r=j+1,up=i-1,dw=i+1; if(l==0)l=n; if(r==n+1)r=1; if(up==0)up=n; if(dw==n+1) dw=1; if(a[i][l][now]==1) cnt++; if(a[i][r][now]==1) cnt++; if(a[up][l][now]==1) cnt++; if(a[up][j][now]==1) cnt++; if(a[up][r][now]==1) cnt++; if(a[dw][l][now]==1) cnt++; if(a[dw][j][now]==1) cnt++; if(a[dw][r][now]==1) cnt++; if(cnt>3||cnt<2) return 1; return 0; } void solve(){ int flag=0; cin>>n>>k; for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ cin>>a[i][j][0]; } } for(int t=0;t<=k;++t){ int now=t,nxt=1+t; for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ if(a[i][j][now]==0){//死了判活 if(pd(i,j,now)==1){ a[i][j][nxt]=1;//修改到下一个回合 } else{ a[i][j][nxt]=a[i][j][now]; } } else{//活了判死 if(pd2(i,j,now)==1){ a[i][j][nxt]=0; } else{ a[i][j][nxt]=a[i][j][now]; } } } } //print(now); if(dd(0,t)&&t!=0){ flag=1; ans=t; break; } } if(flag==1){ cout<<"YES\\n"; cout<<ans<<endl; } else cout<<"NO\\n"; }
★★飞马分隔符★★
对字符串划分若干部分,使得每一部分都不包含子序列FeiMa。而每次划分都需要一个“分隔符”,要求最少个分割符。
出现了一个子序列就划分,就这样。
void solve(){ int f=0,cnt=0; cin>>n; cin>>s+1; for(int i=1;i<=n;++i){ if(f==0&&s[i]==\'F\')f=1; else if(f==1&&s[i]==\'e\')f=2; else if(f==2&&s[i]==\'i\')f=3; else if(f==3&&s[i]==\'M\')f=4; else if(f==4&&s[i]==\'a\')f=5; if(f==5){ cnt++;f=0; } } cout<<cnt<<endl; }
★★温暖的力量★★
把给定的数划分为x份质数 要求x>1 ,然后让x最多
很明显用2和3去分就好。
void solve(){ cin>>n; if(n<=3) cout<<"-1"<<endl; else cout<<n/2<<endl; }
★★翻滚吧硬币★★
给三个圆的半径,求最小的,一个圆切另外两个圆然后绕一周回到该位置,最少的圈数
怎么说呢,是滚动不是滑动,滑动类似外边插一个时针
滚动要贴合,实际上要以圆心为路径的计算。
const int N= 2e6+7; double n,a,c,b; double did(double ra,double rb,double rc){ double Bac=ra+rc; double Bab=ra+rb; double Bbc=rb+rc; double zhou=2*PI*rc; double Jcab=acos((Bac*Bac+Bab*Bab-Bbc*Bbc)/(2*Bac*Bab))*(180.0)/PI; Jcab=360.0-2*Jcab; double Jcba=acos((Bab*Bab+Bbc*Bbc-Bac*Bac)/(2*Bab*Bbc))*(180.0)/PI; Jcba=360.0-2*Jcba; double sum=Jcab*PI*Bac/180.0+Jcba*PI*Bbc/180.0; return sum/zhou; } void solve(){ scanf("%lf%lf%lf",&a,&b,&c); double ans=did(a,b,c); ans=min(ans,did(a,c,b)); ans=min(ans,did(b,c,a)); printf("%.10lf\\n",ans); }
以上是关于兰州大学第一届『飞马杯』程序设计竞赛(同步赛)的主要内容,如果未能解决你的问题,请参考以下文章
兰州大学第一届『飞马杯』程序设计竞赛(同步赛),签到题ACFHJ
兰州大学第一届『飞马杯』程序设计竞赛 - ★★飞马祝福语★★(动态dp)
兰州大学第一届『飞马杯』程序设计竞赛 - ★★体育课排队★★(二分+最大流)