Codeforces Round #739 (Div. 3) 反思

目录

写在前面——反思

A. Dislike of Threes

题目链接

题意

思路

代码

B. Who's Opposite?

题目链接

题意

思路

代码

C. Infinity Table

题目链接

题意

思路

代码

D. Make a Power of Two

题目链接

题意

思路

代码

E. Polycarp and String Transformation

题目链接

题意

思路

代码

反思


写在前面——反思

         这一场打的有点烂,值得反思反思,首先说一下A,做A的时候一直在推式子,在想关于模3或者(x-3) mod 10,还有容斥方面,后面发现有点麻烦,样例不对,才发现这数据可以打暴力...怪我把div3的A题想复杂了。B题是我蠢了,我大致方向是对的,就是有个判断条件没有加,第二发wa跟第一发没区别,加了一个恒成立的式子,白白浪费时间,这个题不应该耗这么久的时间。C题是一个原题,我以前做过,不过if的时候出了点差错,10min有点小多。D题差不多正常时间,这题不亏。

        最让我心痛的是E,怪我,太菜,哎。推答案一推了很久都没有想明白,一开始的方向就错了,曹佬给出了提示我还是没有一下写出来。最让我遗憾的是时间不够了,我在比赛结束的一分钟内写出了程序,然后提交发现A了。但是,就是差这么一分钟,不多不少的一分钟。

        在这张图里面有一个第四行,这是一个20级新生的成绩,有点愧疚,前面写的太慢,还wa了...真是不应该,B题花了太多时间,得到了太多罚时。

A. Dislike of Threes

题目链接

        Problem - A - Codeforces

题意

        求问前面n个数有多少个末尾不是3并且不是3的倍数

思路

        直接暴力

代码

inline void Case_Test()
{
    cin>>n;
    int ans,cnt=0;
    for (int i=1;;i++)
    {
        if (i%3==0||i%10==3) continue;
        cnt++;
        if (cnt==n) {ans=i;break;}
    }
    cout<<ans<<endl;
}

B. Who's Opposite?

题目链接

        Problem - B - Codeforces

题意

        一个这样的环形图,两两对应,已知其中一对,求c对应的哪个数,不满足则输出-1

思路

        首先可以通过已知的一对数来求得一共有多少个,也可以求出一半是多少,如果c在后一半,那么它对应的就是前一半的,反之相反。

代码

inline void Case_Test()
{
    cin>>a>>b>>c;
    n=max(a,b)-min(a,b);
    ma=n*2;
    if (ma<max(a,b)||c>ma) {cout<<"-1"<<endl;return ;}
    if (c>n&&c-n<=ma) {cout<<c-n<<endl;return ;}
    if (c<=n&&c+n<=ma) {cout<<c+n<<endl;return ;}    
    cout<<-1<<endl;
}

C. Infinity Table

题目链接

        Problem - C - Codeforces

题意

        一个这样的图,求问图中x在多少行多少列

思路

        发现左边一列是完全平方,第一行开始推,判断是下还是先下后左

代码

inline void Case_Test()
{
    cin>>k;
    n=(int)sqrt(k);
    if (n*n==k)
    {
        cout<<n<<" "<<1<<endl;
        return;
    }
    x=0;y=n+1;
    tmp=k-n*n;
    if (tmp<=n)
    {
        x+=tmp;
        cout<<x<<" "<<y<<endl;
    }
    else
    {
        x=n+1;y=n+1;
        tmp-=n+1;
        y-=tmp;
        cout<<x<<" "<<y<<endl;
    }
}

D. Make a Power of Two

题目链接

        Problem - D - Codeforces

题意

        给出一个n,求问最少通过多少次操作能够使得n变为2的次方,操作有在右侧加数和删去任意一位

思路

        因为给出的数据不大,我们可以首先打表把2的从1到63次方的表,不能通过数据来只打到31,因为有可能在右侧加入更多的数字来达到。

        然后我们对于每一次数据都循环60多遍来判断,取min。

        判断的话我们将这两个数字都转化成数组,这样容易一一比较,通过双指针来一一匹配,如果当前不满足,那么肯定是要删去的,指针向后移动,记一次数;如果当前相等的话,那么指针都往后,不计数,因为当前是匹配的。最后如果被匹配数指针没有取完,那么剩下的数是还要删去的,加上;如果最后匹配的指针没有取完,那么剩下的数是要在右侧加上的,加上。

        最后输出答案。

代码

inline void init()
{
    for (int i=1;i<=N;i*=2)
        a[++cnt]=i;
    int num=0;
    for (int i=1;i<=N;i*=10)
        b[++num]=i;
    //预处理
}
inline int getlen(int x)
{
    int ans=0;
    while (x)
    {
        x/=10;
        ans++;
    }
    return ans;
}
int c[20],d[20];
inline int check(int n,int x)
{
    
    int num=0;
    int len=getlen(n);
    int l=getlen(x);
    int t=x;
    for (int i=l;i>=1;i--)
    {
        d[l-i+1]=t/b[i];
        t%=b[i];
    }
    int cnt=1;
    int i;
    int ans=0;
    for (i=1;i<=len;i++)
    {
        if (cnt>l) break;
        if (c[i]==d[cnt]) {cnt++;continue;}
        else ans++;
    }
    //cout<<ans+len+1-i+l+1-cnt<<endl;
    return ans+len+1-i+l+1-cnt;
    //ans是之前不匹配计数的  ans后面加的是指针还有多少未指完的个数
}
inline void Case_Test()
{
    cin>>n;
    int t=n;
    int len=getlen(n);
    for (int i=len;i>=1;i--)
    {
        c[len-i+1]=n/b[i];
        n%=b[i];
    }
    int answer=inf,p;
    for (int i=1;i<=cnt;i++)
    {
        //answer=min(answer,check(t,a[i]));
        int m=check(t,a[i]);
        if (answer>m) p=a[i],answer=m;
    }
    cout<<answer<<" "<<p<<endl;
}

E. Polycarp and String Transformation

题目链接

        Problem - E - Codeforces

题意

        一个字符串s,可以选择其中一个字符c让其s中删去所有的c,然后形成新的字符串s加到t右边(t一开始等于s),直到最后s为空。现在已知t,求问之前的字符串s还有删去的顺序,如果不存在那么就输出-1;

思路

        这个题大部分归功于曹佬的提示,不然极大可能做不出来这个题。

        答案2也就是顺序很容易得到,我们对于已知的字符串t的最后一位肯定是最后一个删除的,那么往前面扫,遇到第一个没有出现过的字符记录下来,因为这一个肯定是要删除的,不然后面不可能没有这个字符,所以记录下来,直到这个扫完,这个就出来的。

        答案1这个我想了很久很久,最后在曹佬的提示下完成了,也就是说我们统计每一个字符出现了多少次,记cnt[i],假如字符'a'出现了3次,它是第一个删除的,那么原串(也就是答案1)有3个'a';假如字符'b'出现了4次,它是第二个删除的,那么其实它在原串中有两个'b',因为在一开始的时候有两个,然后删除'a'的时候它没有删除,又被假如到了字符串t中;假如字符'c'出现了6次,它是第三个删除的,那么同理'c'在原串中出现了2次......这样我们能得出所有的字符在原串中出现了多少次,那么我们可以一个for循环或者用字符串copy得到原串s。

        注意:这时候原串不一定是正确答案,我们还得模拟一下操作最后得到的那个t判断是否与我们最开始已知的字符串相等,如果不相等就输出-1,反之输出答案1和答案2

代码

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define debug(a) cout<<#a<<"="<<a<<endl;
#define eps 1e-8
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
bool exist[200];
char ch,ans[200];
int tmp,l,a[200],num[200];
string s;
inline void Case_Test()
{
    int cnt=0;
    cin>>s;
    l=s.length();
    ch=s[l-1];
    cnt=0;
    ans[++cnt]=ch;
    memset(exist,0,sizeof(exist));
    memset(num,0,sizeof(num));
    exist[ch]=1;
    for (int i=l-2;i>=0;i--)
    {
        if (exist[ s[i] ]) continue;
        exist[ s[i] ]=1;
        ans[++cnt]=s[i];
        a[ s[i] ]=cnt;
    }
    for (int i=0;i<l;i++)
        num[s[i]]++;
    int len=0;
    //for (int i=cnt;i>=1;i--) cout<<ans[i]<<" "<<num[ans[i]]<<endl;
    for (int i=1;i<=cnt;i++)
    {
        char c=ans[i];
        int q=cnt+1-i;
        num[c]/=q;
        len+=num[c];
    }
    //for (int i=cnt;i>=1;i--) cout<<ans[i]<<" "<<num[ans[i]]<<endl;
    //cout<<len<<endl;
    string st="";
    for (int i=0;i<len;i++) st+=s[i];
    string answer=st;
    //cout<<answer<<endl;
        string tmp=st;
    for (int i=cnt;i>=1;i--)
    {
        char c=ans[i];
        for (int j=0;j<tmp.length();j++)
            if (tmp[j]==c) tmp.erase(j,1),j--;
        //cout<<tmp<<endl;
        st+=tmp;
    }
    //cout<<st<<endl;
    if (st!=s) {cout<<-1<<endl;return;}
    cout<<answer<<" ";
    for (int i=cnt;i>=1;i--) cout<<ans[i];
    cout<<endl;
}

signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
            clock_t start, end;
            start = clock();
    #endif
    IOS
    int _=1;
    cin>>_;
    while (_--)
    {
        Case_Test();
    }

    #ifndef ONLINE_JUDGE
        end = clock();
        cout << endl << "Runtime: " << (double)(end - start) / CLOCKS_PER_SEC << "s\n";
    #endif
}

反思

        再反思一次吧,希望自己端正态度,继续努力,不要气馁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值