Codeforces Round #506 (Div. 3)(部分)

28 篇文章 0 订阅
19 篇文章 0 订阅

链接:http://codeforces.com/contest/1029
来源:Codeforces

A - Many Equal Substrings(最长的真前后缀)

  题意:给你一个子串t,让你找到最短的s包含k个子串
  思路:找到最长的公共前后缀以后,我们可以先输出t,然后t中的最长公共前后缀无需再输出(重复),只输出不重复的部分即可。

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,k;string s;
	cin>>n>>k>>s;
	n=s.length();
	int index=0;
	for(int i=1;i<n;i++)
        if(s.substr(0,i)==s.substr(n-i,i))
            index=i;
    cout<<s;
    for(int i=1;i<k;i++)
        cout<<s.substr(index,n-index);
}

B - Creating the Contest

题意:给你n个题,对应的题目难度为a[i],找到满足的最长的序列满足a[i]>=2*a[i-1]
思路:将给出的题目难度排序后,根据条件遍历数组即可得到最大的长度。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int Max_n=2e5+10;
int a[Max_n];

int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	int cnt=1,res=1;//res至少有一个
	for(int i=2;i<=n;i++){
		if(a[i]<=2*a[i-1])	cnt++,res=max(res,cnt);
		else	cnt=1;
	}
	printf("%d\n",res);
	return 0;
}

C - Maximal Intersection(思维)

题意:给定n个线段端点是l,r,这n个线段有一段公共的区间。问删除那条线段可以使这个公共区间变得最长。
思路:我们可以删除lmax或者rmin所代表的线段,这两种情况即可得到最大长度。

#include<bits/stdc++.h>
using namespace std;

const int Max_n=3e5+10;

struct Edge{
    int s,e;
}edge[Max_n];

priority_queue<int>qs;
priority_queue<int,vector<int>,greater<int> >qe;

int main(){
   int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&edge[i].s,&edge[i].e);
        qs.push(edge[i].s);
        qe.push(edge[i].e);
    }
//    cout<<qs.top()<<endl;
//    cout<<qe.top()<<endl;
    int mmax=0,temp=0;
    for(int i=1;i<=n;i++){
        if(qs.top()==edge[i].s){
            qs.pop();
            bool flag=false;
            if(qe.top()==edge[i].e){
                qe.pop();
                flag=true;
            }
            temp=qe.top()-qs.top();
            qs.push(edge[i].s);
            if(flag) qe.push(edge[i].e);
            mmax=max(temp,mmax);
        }
        if(qe.top()==edge[i].e){
            qe.pop();
            bool flag=false;
            if(qs.top()==edge[i].s){
                qs.pop();
                flag=true;
            }
            temp=qe.top()-qs.top();
            qe.push(edge[i].e);
            if(flag) qs.push(edge[i].s);
            mmax=max(temp,mmax);
        }
    }
    printf("%d\n",mmax);
	return 0;
}

D - Concatenated Multiples(数论)

  题意:输入n,k,代表我们有n个数,n个数中任意两个数链接起来能够被k整除的组合一共有多少个?
  思路:(xlog10(y)+1%mod+y%mod)%mod=0的时候满足题意。我们可以先把x×log10(y)+1的所有情况枚举出来,也就是记录x后面的10位的余数的情况,例如45和1%11的情况,先记录45×10%11的余数的情况,也就是10,那么1%11为1,此时他们相加为11,可以被11整除。(x%mod+y%mod)%mod=0,x代表450,y代表1,我们可以记录下来xm余数的情况,也就是找到mod-y的情况。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int Max_n = 2e5+10;
ll a[Max_n];
map<ll,ll>m[20];

int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    /**记录x后面跟j为的余数的个数*/
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        ll x=a[i];
        for(ll j=1;j<=10;j++){
            x*=10;
            x%=k;
            m[j][x]++;
        }
    }
    ll sum=0;
    for(int i=1;i<=n;i++){
        ll len=log10(a[i])+1;
        ll y=(k-a[i]%k)%k;
        /**当前值余数和别的数(提前打表)做链接*/
        sum+=m[len][y];
        ll x=1;
        for(int j=1;j<=len;j++)
            x*=10;
        /**去掉和自身做链接的情况*/
        if((((a[i]%k)*(x%k))%k+a[i]%k)%k==0)
            sum--;
    }
    printf("%lld\n",sum);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值