Codeforces Round #449 div.2 题解及心路历程

来源:互联网 发布:php artisan数据库 编辑:程序博客网 时间:2024/05/29 17:33

  • 当时的情况
  • 题解
    • T1
    • T2
    • T3
    • T4
    • T5
  • 彩蛋

http://codeforces.com/contest/897
这一次洛谷珂学家玩了起来,为了信仰,我冒着掉分的风险修仙打比赛.由于我是个蒟蒻,只能做一下div.2了.

当时的情况

2017年12月2日晚22:05,比赛正式的开始了.看到第一题.100*100,暴力不由分说打上去.4分钟提交搞定.毫不犹豫做B题,把前20个数写下来,突然我发现了什么,刷刷地写了起来.19分钟B题.再过一会去看一看,pretest全都过了.我怕有人hack我,所以没有锁题.(反正我是个从来找不到别人代码漏洞的萌新,我就干脆不看别人代码了)然后后面三个题一看直接就跪了啊.E题看不懂,交互题不会打,那就做C题.我搞了两个小时,推了好久,终于在离结束还有6分钟的时候推出了标算.然后我花6分钟的时间把标算打挂了,比赛遗憾结束.
因为前两题效率的优势再加上有人FST,我从837变成803,获得了32分.我还是很高兴的.
这场比赛还是要补掉的.那就今天了.

题解

T1

字符串操作,非常简单,地道的水题.

#include<bits/stdc++.h>using namespace std;char s[150];int main(){int n,k;cin>>n>>k>>s+1;for (int i=1;i<=k;++i)  {  int l,r;char c,p;  cin>>l>>r>>c>>p;  for (int j=l;j<=r;++j) if (s[j]==c) s[j]=p;  }cout<<s+1;}

T2

求前n个长度是偶数的回文数之和modk的值.你会发现偶数回文数就是i根据它的个位右侧镜面对称所得到的数字.
我不会神操作,用一个数组存储每一位来计算之.

#include<bits/stdc++.h>using namespace std;typedef long long ll;ll k,p;ll huiwen(ll k){int i,bit[20],p=0;for (;k;k/=10) bit[++p]=k%10;//把k分解掉for (i=1;i<=p;i++) bit[i+p]=bit[i];//复制一遍reverse(bit+1,bit+p+1);//把前面p个翻转就得到了所求回文数p*=2;ll ans=0;for (i=1;i<=p;i++) ans=ans*10+bit[i];//回文数前面和后面一样return ans;}int main(){ll s=0;scanf("%lld%lld",&k,&p);for (ll i=1;i<=k;i++) s=(s+huiwen(i))%p; printf("%lld",s);}//虽然复杂,但是能过.

T3

有很多字符串,它们是通过递归的方式形成的.
f0 is “What are you doing at the end of the world? Are you busy? Will you save us?”.

She wants to let more people know about it, so she defines fi =  “What are you doing while sending “fi - 1”? Are you busy? Will you send “fi - 1”?” for all i ≥ 1.

For example, f1 is

“What are you doing while sending “What are you doing at the end of the world? Are you busy? Will you save us?”? Are you busy? Will you send “What are you doing at the end of the world? Are you busy? Will you save us?”?”. Note that the quotes in the very beginning and in the very end are for clarity and are not a part of f1.
首先原字符串和递归方法都是已知不变的,首先判断是否返回小数点,就是看字符串长度是否小于k.因为k<=1e18,可算出到第53个字符串就不可能会出现小数点了.接下来把字符串分为五份,a1,f[n-1],a2,f[n-1],a3,(看下面代码)然后判断第k个在哪一个部分里,如果出现在f[n-1]里就往下一层递归,直到n=0为止.

#include<bits/stdc++.h>#define boss 100000#define r1 34 //a1.size()#define r2 32 //a2.size()#define r3 2  //a3.size()#define da 9223372036854775807 //max_long longusing namespace std;typedef long long ll;int t,n;ll k;char f0[]={"What are you doing at the end of the world? Are you busy? Will you save us?"},//末日时在做什么?有没有空?可以来拯救吗?     f1[]={"What are you doing while sending ?Are you busy? Will you send ?"},     f2[]={"What are you doing while sending \"What are you doing at the end of the world? Are you busy? Will you save us?\"? Are you busy? Will you send \"What are you doing at the end of the world? Are you busy? Will you save us?\"?"};string f[boss+10]={f0,f2},       a1="What are you doing while sending \"",//递归所用的三个字符串       a2="\"? Are you busy? Will you send \"",       a3="\"?";ll changdu[boss+10]={75};//也可以打表.char work(int n,ll k){if (k>changdu[n]) return '.';if (n==0) return f0[k];if (k<r1) return a1[k];k-=r1;if (k<changdu[n-1]) return work(n-1,k);k-=changdu[n-1];if (k<r2) return a2[k];k-=r2;if (k<changdu[n-1]) return work(n-1,k);k-=changdu[n-1];if (k<r3) return a3[k];return '.';}//这样就不用解释了吧.int main(){int i;string ans="";for (i=1;i<=55;++i) changdu[i]=2*changdu[i-1]+68;for (i=56;i<=boss;++i) changdu[i]=da;for (scanf("%d",&t);t--;)   {  scanf("%d%lld",&n,&k);  ans.push_back(work(n,k-1));  }cout<<ans;}

T4

本题为交互题.给出一串纸,每次给你一个不超过c的正整数,你可以把它写在任何一张纸上或者替换掉原先纸上的那一个数字,输出你写的那张纸的编号.如果在任何时候这串纸上每一张纸都写了数字并且成非降序排列,你就赢了,直接结束程序.
细节,100%有解.分两种情况讨论给的数字x:
x>c/2,x应该被填在后面.从后往前找,找到第一个小于x的数,替换之;
其余情况从前往后找第一个大于x的数字,替换之.
当然看到空格位就直接填了.

#include<cstdio>int a[1010],n,m,c,x,i;int main(){for (scanf("%d%d%d",&n,&m,&c);m--;)  {  scanf("%d",&x);  if (x*2>c) for (i=n;a[i]>=x;--i);  else for (i=1;a[i]&&a[i]<=x;++i);  printf("%d\n",i),fflush(stdout),a[i]=x;  for (i=1;i<=n;i++) if (a[i]==0) break;  if (i>n) return 0;  }}

我看了代码之后才知道这个fflush怎么用,真不能怪我.

T5

这个题一看就要用某种数据结构.而且这个题出的非常的好,极大地减少了输入量.当然用这样的方法产生随机数也不是第一次见了.
这里用了二叉查找树.
每次一看到这种诡异背景的题目我给变量的取名也变骚了.当然不会有大写字母的.

#include<bits/stdc++.h>#define catholly 100000using namespace std;typedef long long ll;const int willem=1e9+7;int n,m,k,seed,l,r,ret,ans,vmax;ll c1,c2,a[catholly+10],x,y;struct seniorious{ll x;int len;}talisman[catholly+10];inline int cmp(seniorious a,seniorious b){return a.x<b.x;}set<int> s;set<int>::iterator p;inline int read(){int x=0;char c=getchar();for (;!isdigit(c);c=getchar());for (;isdigit(c);c=getchar()) x=x*10+c-'0';return x;}inline int rnd(){ret=seed;seed=(seed*7LL+13)%willem;return ret;}inline ll quick_power(ll a,int b){ll s=1;for (a%=y;b;b>>=1,a=a*a%y) if (b&1) s=s*a%y;return s; }inline void write(ll x){register int bit[20],p=0,i;if (x==0) {putchar(48);return;}for (;x;x/=10) bit[++p]=x%10;for (i=p;i>0;--i) putchar(bit[i]+48);}int main(){int i;n=read(),m=read(),seed=read(),vmax=read();for (i=1;i<=n;++i) a[i]=rnd()%vmax+1;for (i=0;i<=n+1;++i) s.insert(i);for (;m--;)  {  k=rnd()%4+1,l=rnd()%n+1,r=rnd()%n+1;  if (l>r) swap(l,r);  x=k==3?rnd()%(r-l+1)+1:rnd()%vmax+1;  if (k==4) y=rnd()%vmax+1;  if (k==1)    {    p=--s.upper_bound(r),c2=a[*p];//这样找到l和r就要用到二分查找.    p=s.lower_bound(r+1);    if (*p!=r+1) s.insert(r+1),a[r+1]=c2;    p=--s.upper_bound(l),c1=a[*p];    if (*p!=l) s.insert(l);a[l]=c1+x;    for (p=s.upper_bound(l);*p<=r;++p) a[*p]+=x;//一路过去全部加x    }  if (k==2)    {    p=--s.upper_bound(r),c2=a[*p];    p=s.lower_bound(r+1);    if (*p!=r+1) s.insert(r+1),a[r+1]=c2;    p=--s.upper_bound(l),c1=a[*p];    if (*p!=l) s.insert(l);a[l]=x;//前面操作相同,就是这里变成了x    for (p=s.upper_bound(l);*p<=r;p=s.upper_bound(l)) s.erase(*p);//一路删过去,因为全部都变成x了.    }  if (k==3||k==4)    {    p=--s.upper_bound(l),talisman[ans=1]=(seniorious){a[*p],l};    for (++p;*p<=r;++p) talisman[++ans]=(seniorious){a[*p],*p};    for (i=1;i<=ans;++i) talisman[i].len=i==ans?r-talisman[i].len+1:talisman[i+1].len-talisman[i].len;    if (k==3)      {      sort(talisman+1,talisman+ans+1,cmp);      for (i=1;i<=ans&&x>talisman[i].len;++i) x-=talisman[i].len;      write(talisman[i].x),puts("");        }    else       {      ll sum=0;      for (i=1;i<=ans;++i) sum=(sum+quick_power(talisman[i].x,x)*talisman[i].len)%y;      write(sum),puts("");//这里就不用解释了.      }    }  }}

彩蛋

div.1的最后一题可以打暴力.加两个优化就可以了.

#pragma GCC optimize("Ofast,no-stack-protector")#pragma GCC target("avx")//非常神奇的优化,具体怎么回事我去网上搜也没搜出来#include<bits/stdc++.h>#define re registerint a[100010],n,m;int main(){re int i;float x;//float优化,大佬scanf("%d%d",&n,&m);for (i=1;i<=n;++i) scanf("%d",&a[i]);for (re int k,l,r,s;m--;)  {  scanf("%d%d%d%f",&k,&l,&r,&x);  if (k==1) for (i=l;i<=r;++i) a[i]-=a[i]>x?x:0;   else     {    for (s=0,i=l;i<=r;++i) a[i]==x?++s:0;    printf("%d\n",s);    }  }}
原创粉丝点击