Codeforces Round #246 (Div. 2)
来源:互联网 发布:seo基础视频教程 编辑:程序博客网 时间:2024/05/24 06:51
You have an array a[1], a[2], ..., a[n], containing distinct integers from1 ton. Your task is to sort this array in increasing order with the following operation (you may need to apply it multiple times):
- choose two indexes, i and j (1 ≤ i < j ≤ n;(j - i + 1) is a prime number);
- swap the elements on positions i and j; in other words, you are allowed to apply the following sequence of assignments:tmp = a[i], a[i] = a[j], a[j] = tmp (tmp is a temporary variable).
You do not need to minimize the number of used operations. However, you need to make sure that there are at most5n operations.
The first line contains integer n (1 ≤ n ≤ 105). The next line containsn distinct integersa[1], a[2], ..., a[n](1 ≤ a[i] ≤ n).
In the first line, print integer k (0 ≤ k ≤ 5n) — the number of used operations. Next, print the operations. Each operation must be printed as "ij" (1 ≤ i < j ≤ n;(j - i + 1) is a prime).
If there are multiple answers, you can print any of them.
33 2 1
11 3
21 2
0
44 2 3 1
32 41 22 4题意:每次交换两个数,要求这两个数的位置差,是素数。思路:根据哥德巴赫猜想,一个合数可以表示成最多5个素数的和,所以j-i+1最多表示成5个素数,保证最多交换5*n次。先打素数表,然后从最小的数字一个个模拟往前放即可,放的时候走的步数直接拆成都是质数即可。#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<map>#include<cmath>#include<algorithm>using namespace std;const int maxn=100010;bool vis[maxn];int n,a[maxn],w[maxn];void init(){ memset(vis,0,sizeof(vis)); int k=sqrt(n); vis[1]=1; for(int i=2;i<=k;i++) { if(vis[i])continue; for(int j=i*i;j<=n;j+=i) vis[j]=1; }}int main(){ scanf("%d",&n); init(); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); w[a[i]]=i; } int cur=1; int ans=0; vector<pair<int,int> > v; while(cur<=n) { while(w[cur]!=cur) { for(int j=cur;;j++) { if(!vis[w[cur]-j+1]) { v.push_back(make_pair(j,w[cur])); ans++; int tmp=w[cur]; w[cur]=j; w[a[j]]=tmp; swap(a[tmp],a[j]); break; } } } cur++; } printf("%d\n",ans); for(int i=0;i<ans;i++) cout<<v[i].first<<" "<<v[i].second<<endl; return 0;}题意:给你一个长度不超过10^5的字符串。要你按长度输出和后缀完全匹配的的前缀的长度。和该前缀在整个串中出现的次数。D. Prefixes and SuffixesYou have a string s = s1s2...s|s|, where |s| is the length of string s, and si its i-th character.
Let's introduce several definitions:
- A substring s[i..j] (1 ≤ i ≤ j ≤ |s|) of string s is string sisi + 1...sj.
- The prefix of string s of length l (1 ≤ l ≤ |s|) is string s[1..l].
- The suffix of string s of length l (1 ≤ l ≤ |s|) is string s[|s| - l + 1..|s|].
Your task is, for any prefix of string s which matches a suffix of string s, print the number of times it occurs in string s as a substring.
InputThe single line contains a sequence of characters s1s2...s|s| (1 ≤ |s| ≤ 105) — string s. The string only consists of uppercase English letters.
OutputIn the first line, print integer k (0 ≤ k ≤ |s|) — the number of prefixes that match a suffix of string s. Next print k lines, in each line print two integers li ci. Numbers li ci mean that the prefix of the length li matches the suffix of length li and occurs in string s as a substring ci times. Print pairs li ci in the order of increasing li.
Sample test(s)InputABACABA
Output31 43 27 1
InputAAA
Output31 32 23 1
思路:我使用扩展KMP做的,先求出next数组,如果next[i]==n-i,则表示前缀有后缀相同,然后输出前缀出线的次数(也可以用next数组得到)#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100010;char s[maxn];int next[maxn],n;int cnt[maxn],ans[maxn];void getnext(){ n=strlen(s); next[0]=n; int j=0; while(j+1<n&&s[j]==s[j+1])j++; next[1]=j; int k=1; for(int i=2;i<n;i++) { int p=k+next[k]-1; int l=next[i-k]; if(i+l<p+1)next[i]=l; else { j=max(0,p-i+1); while(i+j<n&&s[i+j]==s[j])j++; next[i]=j; k=i; } }}int main(){ //freopen("in.txt","r",stdin); scanf("%s",s); getnext(); memset(cnt,0,sizeof(cnt)); for(int i=0;i<n;i++) if(next[i]) cnt[next[i]]++; int x=cnt[n]; for(int i=n-1;i>=1;i--)//统计长度为i的前缀出现的次数 { if(cnt[i]==0)continue; cnt[i]+=x; x=cnt[i]; } int num=0; for(int i=0;i<n;i++) { if(next[i]==n-i)ans[num++]=next[i];//判断是不是前缀与后缀相同 } sort(ans,ans+num); printf("%d\n",num); for(int i=0;i<num;i++) { printf("%d %d\n",ans[i],cnt[ans[i]]); } return 0;}
也可以直接用kmp做,具体详见代码
#include<iostream>#include<cstdio>#include<cstring>#define INF 0x3f3f3f3fusing namespace std;const int N = 100005;char s[N];int next[N], n, ans[N], ansn = 0;void get_next(char *seq, int m){ int len=strlen(seq); next[0]=-1; int i=0,j=-1; while(i<n) { if(j==-1||seq[i]==seq[j]) { i++; j++; next[i]=j; } else j=next[j]; }}int vis[N];int main(){ //freopen("in.txt","r",stdin); int i = 0; scanf("%s", s + 1); n = strlen(s + 1); get_next(s, n); int t = next[n]; while (t) { ans[ansn++] = t;//next表示适配后应该从那个开始在跟当前位置比较,即前缀有多少长度与当前后缀匹配 t = next[t]; } for (i = n; i > 0; i--) vis[next[i]]++; for (i = n; i > 0; i--) vis[next[i]] += vis[i];//前缀出线的次数 printf("%d\n", ansn + 1); for (i = ansn - 1; i >= 0; i--) printf("%d %d\n", ans[i], vis[ans[i]] + 1); printf("%d %d\n", n, vis[n] + 1); return 0;}
- Codeforces Round #246 (Div. 2)
- Codeforces Round #246 (Div. 2)
- Codeforces Round #246 (Div. 2)
- Codeforces Round #246 (Div. 2)
- Codeforces Round #246 (Div. 2)
- Codeforces Round #246 (Div. 2)
- Codeforces Round #246 (Div. 2)
- 【索引】Codeforces Round #246 (Div. 2)
- Codeforces Round #102 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #104 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #107 (Div. 2)
- Codeforces Round #108 (Div. 2)
- Codeforces Round #110 (Div. 2)
- Codeforces Round #122 (Div. 2)
- 设计模式 - 模板方法模式(template method pattern) JFrame 详解
- 真理常常很简单
- inline-block在IE8,9的间隙问题
- we热二胎热
- java中的匿名内部类总结
- Codeforces Round #246 (Div. 2)
- 习题3-2 分子量 UVa1586
- 小结:sga_max_size和sga_target
- Libevent示例程序3 定时器程序续
- activity生命周期
- Java序列化与反序列化
- python 远程线程注入代码
- 习惯养成
- 创建cocos2d-x+lua项目