链接: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;
}