SRM 677 div2
通过数:2
250:
问[L,R]区间内有多少个素数且它是回文数的数。
由于数据范围比较小,直接暴力就可以。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
class PalindromePrime {
public:
int count(int, int);
};
const int MAXN = 1000 + 50;
int prime[MAXN], cnt;
int vis[MAXN];
int a[10];
bool parliment(int u)
{
int tcnt = 0;
while(u) a[++tcnt] = u % 10, u /= 10;
int head = 1, rear = tcnt;
while(head < rear){
if(a[head] != a[rear]) return false;
head++, rear--;
}
return true;
}
void init()
{
for(int i = 1 ; i < MAXN ; i++) vis[i] = 0;
cnt = 0;
for(int i = 2 ; i < MAXN ; i++){
if(vis[i]) continue;
if(parliment(i)) prime[cnt++] = i;
for(int now = i ; now < MAXN ; now += i) vis[now] = 1;
}
}
int PalindromePrime::count(int L, int R) {
init();
int t1, t2;
t1 = t2 = 0;
while(t1 < cnt && prime[t1] < L) t1++;
while(t2 < cnt && prime[t2] <= R) t2++;
return t2 - t1;
}
<%:testing-code%>
//Powered by [KawigiEdit] 2.0!
550:
四个字符串,可以合成一个字符串,这个字符串的连续子串中包含这四个字符串。
问这个合成的字符串最短多长。
先记录下四个字符串前后连接时相同的地方多少个就可以,手残调了一段时间。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
class FourStrings {
public:
int shortestLength(string, string, string, string);
};
int len[15][15];
string str[15];
void solve_len()
{
for(int i = 1 ; i < 5 ; i++){
for(int j = 1 ; j < 5 ; j++){
if(i == j) continue;
else{
len[i][j] = 0;
for(int t1 = 0 ; t1 < (int)str[i].size() ; t1++){
int ok = 1;
for(int t2 = t1 ; t2 - t1 < str[j].size() && t2 < str[i].size(); t2++){
if(str[i][t2] != str[j][t2 - t1]){
ok = 0;
break;
}
}
if(ok){
len[i][j] = min(str[i].size() - t1 , str[j].size());
break;
}
}
}
}
}
// for(int i = 1 ; i <= 4 ; i++){
// for(int j = 1 ; j <= 4 ; j++) printf("%d ", len[i][j]);
// printf("\n");
// }
// printf("\n");
}
int vis[5];
int number[5];
int ans;
void dfs(int u)
{
if(u == 5){
int temp = 0;
int pre = number[1];
for(int i = 2 ; i <= 4 ; i++){
temp += len[pre][number[i]];
if(len[pre][number[i]] < str[number[i]].size()) pre = number[i];
}
// if(temp == 4){
// for(int i = 1 ; i <= 4 ; i++) printf("%d ", number[i]);
// printf("\n");
// }
ans = max(ans, temp);
}
else{
for(int i = 1 ; i < 5 ; i++){
if(vis[i] == 0){
number[u] = i;
vis[i] = 1;
dfs(u + 1);
vis[i] = 0;
}
}
}
}
int FourStrings::shortestLength(string a, string b, string c, string d) {
str[1] = a;
str[2] = b;
str[3] = c;
str[4] = d;
solve_len();
for(int i = 1 ; i < 5 ; i++) vis[i] = 0;
ans = 0;
for(int i = 1 ; i < 5 ; i++){
if(vis[i] == 0){
vis[i] = 1;
number[1] = i;
dfs(2);
vis[i] = 0;
}
}
ans = a.size() + b.size() + c.size() + d.size() - ans;
return ans;
}
<%:testing-code%>
//Powered by [KawigiEdit] 2.0!
900:
好题啊~
给n个点,起点0,终点1。现在给出边,每个边有一个英文字母编号。
每个点可以重复走,问从起点走到终点、最终走过的边连成的字符串是回文串的最短路径长度多少。
想的时候并没有什么思路,感觉数据范围很想状态压缩DP,但是由于每个点可以重复走就没有办法DP了。
实际上这个思路从开始就是错误的,因为把走的过程看成单纯的从一个点走到另外一个点。然而由于后面走的点没有办法计算,所以这样无法求解。
如果把问题转化一下,看成对于已经是回文串的一段来说,分别向左向右扩展两个相同字符的节点,那么这题就解决了。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
class PalindromePath {
public:
int shortestLength(int, vector <int>, vector <int>, string);
};
const int MAXN = 20 + 3;
int dp[5][MAXN][MAXN];
int edge[MAXN][MAXN];
vector<int>lin[MAXN];
int PalindromePath::shortestLength(int n, vector <int> a, vector <int> b, string c) {
int flag = 0;
memset(edge, -1, sizeof(edge));
for(int i = 0 ; i < n ; i++) edge[i][i] = 1, lin[i].clear();
memset(dp, -1, sizeof(dp));
for(int i = 0 ; i < n ; i++) dp[flag][i][i] = 0;
for(int i = 0 ; i < (int)a.size() ; i++){
edge[a[i]][b[i]] = edge[b[i]][a[i]] = c[i] - 'a' + 1;
dp[!flag][a[i]][b[i]] = dp[!flag][b[i]][a[i]] = 1;
lin[a[i]].push_back(b[i]);
lin[b[i]].push_back(a[i]);
}
// for(int i = 1 ; i <= n ; i++)
// if(dp[flag][0][1] != -1) return dp[flag][0][1];
for(int len = 2 ; len <= (n * n) ; len++){
for(int x = 0 ; x < n ; x++){
for(int y = 0 ; y < n ; y++){
if(dp[flag][x][y] == len - 2){
for(int i = 0 ; i < (int)lin[x].size() ; i++){
for(int j = 0 ; j < (int)lin[y].size() ; j++){
int u = lin[x][i];
int v = lin[y][j];
if(edge[u][x] == edge[v][y]) dp[(flag + 2) % 3][u][v] = len;
}
}
}
}
}
if(dp[flag][0][1] != -1) return dp[flag][0][1];
flag = (flag + 1) % 3;
}
int ans = MAXN*MAXN + 1;
for(int i = 0 ; i < 4 ; i++) if(dp[i][0][1] != -1) ans = min(ans, dp[i][0][1]);
if(ans == MAXN * MAXN + 1) return -1;
else return ans;
}
<%:testing-code%>
//Powered by [KawigiEdit] 2.0!