codeforces 1029(A-D)

版权声明:转载请告知博主并要注明出处嗷~ https://blog.csdn.net/Akatsuki__Itachi/article/details/82177473

div3的题比div2都要难了吗......

比赛那天是晚上11点,困的不行,做了几分钟A题没A掉一怒之下就去睡觉了,昨晚又抓过来重新做了下,div3体验极差。。

A Many Equal Substrings

题意:给一个串t,构造一个尽可能长度小字符串,使得这个字符串里有k个子串t

一开始WA在6组,后来想了想,有一种情况忘了考虑

4 3

aaaa

put:aaaaaa

只需要找出最大的前缀和后缀相等的情况即可,然后让下标sub停留在前缀的后一个字符处。

最后输出一次原串,k-1次从sub开始的子串。

(利用kmp的next数组也可以做

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define memset(a,v)  memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(1e6);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
int main()
{
    int n,k;
    string t;
    cin>>n>>k>>t;
    int sub=0;
    string str1,str2;
    for(int i=0;i<n-1;i++)
    {
        str1+=t[i];
        str2=t[n-i-1]+str2;
        if(str1==str2)
            sub=i+1;
    }
    cout<<t;
    for(int i=1;i<k;i++)
        cout<<t.substr(sub);
    cout<<endl;
}

B Creating the Contest

题意:给出一个上升的数组。要求找出最大长度的子数组,对于子数组里面的数值,要保证a[i-1]*2>=a[i].

按照AC的代码题意是这样的,但是原文叙述有很多不对的地方(我记得当时比赛B题改了题面,不过我没有注意看

一开始就翻译成了对于子数组里面的数字,对于每一个i,从1~i-1的每个数都要使得a[j]*2>=a[i]   1<=j<=i-1,于是二分就WA了。

。。。

枚举O(n),满足条件ans+1,否则重置ans

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define memset(a,v)  memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(2*1e5);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
int a[MAXL+50];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",a+i);
    int ans=0,temp=1;
    for(int i=1;i<n;i++)
    {
        if(a[i-1]*2>=a[i])
            temp++;
        else
            ans=max(ans,temp),temp=1;
    }
    cout<<max(ans,temp)<<endl;
}

C Maximal Intersection

又是一道前后缀的题

题意:给出n条线段,问删除哪一个线段可以使得其它线段的交集最小。

枚举每一个线段 i ,都可以假设删除此条线段,这样的结果就是 1~i-1线段的交集和i+1~n线段的交集,再取交集。

那么就可以维护一个前缀数组和后缀数组存放线段的交集。

ps:交集:左区间的最大值,右区间的最小值。

       并集:左区间的最小值,右区间的最大值。
 

做完后想了想,代码里的排序删掉也可以,不影响最终结果。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define memset(a,v)  memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(3*1e5);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
struct node
{
    int l,r;
    bool operator < (const node &cmp)const{
        return l==cmp.l ? r<cmp.r : l<cmp.l;
    }
}a[MAXL+50],dp1[MAXL+50],dp2[MAXL+50];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].l,&a[i].r);
    sort(a+1,a+n+1);
    int max1=a[1].l,min1=a[1].r;
    int max2=a[n].l,min2=a[n].r;
    for(int i=1;i<=n;i++)
    {
        max1=max(max1,a[i].l);
        min1=min(min1,a[i].r);
        dp1[i].l=max1,dp1[i].r=min1;
        max2=max(max2,a[n-i+1].l);
        min2=min(min2,a[n-i+1].r);
        dp2[n-i+1].l=max2,dp2[n-i+1].r=min2;
    }
    int ans=0;
    ans=max(ans,dp2[2].r-dp2[2].l);
    ans=max(ans,dp1[n-1].r-dp1[n-1].l);
    for(int i=2;i<n;i++)
        ans=max(ans,min(dp1[i-1].r,dp2[i+1].r)-max(dp1[i-1].l,dp2[i+1].l));
    cout<<ans<<endl;
}

D Concatenated Multiples

这就是体验极差的一道题,div3的D题没做出来。。。

后来看到题解写了一个公式,恍然大悟,遂奋键疾码,AC此题 :)

题意:有n个数,每两个数之间可以连接(比如123和456,连接后就是123456)组成新的数,找出有多少个新组成的数可以被k整除。

两个数x,y,如果连接后的数能被k整除,当且仅当:

( x*pow(10,len)%k+y%k )% k == 0      ①

即: x*pow(10,len)%k+y%k == k 或者 0     ②

其中 len为y的位数。

所以x*pow(10,len)%k =  ( k - y%k ) %k    ,后面再%k是式②余数为0的情况。

这样我们就可以预处理出前面的式子,即 len=i 时,x*pow(10,i)%k 的个数

然后枚举一遍数据,计算 ( k - y%k ) %k ,如果两个结果相等,那么就加在ans里。

有一种情况需要额外处理,当自身与自身连接被k整除时,要减去这种情况。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#define memset(a,v)  memset(a,v,sizeof(a))
#define eps 1.0E-8
using namespace std;
const int MAXL(2*1e5);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
typedef long long int LL;
int n,k;
int a[MAXL+50];

map<int,int> mp[20];

int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",a+i);
        LL x=a[i];
        for(int j=1; j<=10; j++)
        {
            x*=10;
            x%=k;
            mp[j][x]++;
        }
    }
    
    LL ans=0;
    for(int i=1; i<=n; i++)
    {
        int len=log10(a[i])+1;
        ans+=mp[len][(k-a[i]%k)%k];
        LL x=1;
        for(int j=1; j<=len; j++)
            x=x*10%k;
        if(((x*a[i])%k+a[i]%k)%k==0)
            ans--;
    }
    
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/Akatsuki__Itachi/article/details/82177473