Codeforces #265 div1
2015-08-29 18:00:22
【传送门】
小结:开的VP,这场题目质量很高~比赛中24min过了A题就“吃面包了”。。。
第二题自己想了个很麻烦的做法... 打不完 - -,赛后补了前3题。
A题:技巧,思维。
题意:给出一个只用前p个小写英文字母的字符串,而且不存在长度>=2的回文子串,让你构造出字典序下一个这样的串(且长度不变)。串长<=1000
思路:很自然地想到给原来的串不断地+1(在p进制下)然后 n^2 判断是否符合条件,但是这样太慢。有下面更快的判断方法。
想到如果当前进位到第pos位(设最右位为第一位),1~pos-1位都没发生变化,因此1~pos-1位都不会出现回文。那么我们只需要使得第pos位和第pos-1位以及pos-2位不同即可(不形成长度为2/3的回文),因为如果能形成更长的回文,必须要使得中间部分回文,而前pos-1位并不会出现这样的情况。所以在模拟时先算出涉及进位的最高位,然后补全后面的位,方法如上述。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; int n,p; char s[1010]; int main(){ scanf("%d%d",&n,&p); scanf("%s",s + 1); int pos = n,c = 1; while(pos >= 1){ s[pos] += c; if(s[pos] - 'a' >= p){ pos--; c = 1; } else{ if((pos > 1 && s[pos - 1] == s[pos]) || (pos > 2 && s[pos - 2] == s[pos])){ c = 1; } else{ break; } } } if(pos == 0){ printf("NO\n"); return 0; } for(int i = pos + 1; i <= n; ++i){ bool flag = false; for(int j = 0; j < p; ++j){ s[i] = j + 'a'; if(i > 1 && s[i - 1] == s[i]) continue; if(i > 2 && s[i - 2] == s[i]) continue; flag = true; break; } if(!flag){ printf("NO\n"); return 0; } } printf("%s\n",s + 1); return 0; }
B题:暴力,技巧。
题意:给出8个点的三个坐标,每个点的x,y,z是打乱的,让你重排每个点的坐标使得8个点形成边长不为9的立方体。
思路:貌似也只能暴力... 但是有个技巧:保持第一个点不变,暴力7个点,因为如果把x,y,z轴交换,立方体依旧是立方体。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; int D[9][4]; int used[10]; bool flag; int s[9][4]; ll Dis(int a1,int b1,int c1,int a2,int b2,int c2){ return (ll)(a2 - a1) * (a2 - a1) + (ll)(b2 - b1) * (b2 - b1) + (ll)(c2 - c1) * (c2 - c1); } bool Check(){ ll dis[30]; int tot = 0; for(int i = 1; i <= 8; ++i){ for(int j = i + 1; j <= 8; ++j){ dis[++tot] = Dis(s[i][1],s[i][2],s[i][3],s[j][1],s[j][2],s[j][3]); } } sort(dis + 1,dis + 28 + 1); if(!dis[1]) return false; for(int i = 1; i < 12; ++i) if(dis[i] != dis[i + 1]) return false; for(int i = 13; i < 24; ++i) if(dis[i] != dis[i + 1]) return false; for(int i = 25; i < 28; ++i) if(dis[i] != dis[i + 1]) return false; if(dis[13] != 2 * dis[1] || dis[25] != 3 * dis[1]) return false; return true; } void Dfs(int p){ if(flag) return; if(p > 7){ if(Check()){ flag = true; printf("YES\n"); for(int i = 1; i <= 8; ++i) printf("%d %d %d\n",s[i][1],s[i][2],s[i][3]); } return; } Dfs(p + 1); swap(s[p][1],s[p][2]); Dfs(p + 1); swap(s[p][2],s[p][3]); Dfs(p + 1); swap(s[p][1],s[p][2]); swap(s[p][2],s[p][3]); Dfs(p + 1); swap(s[p][2],s[p][3]); Dfs(p + 1); swap(s[p][2],s[p][3]); swap(s[p][1],s[p][2]); Dfs(p + 1); } int main(){ for(int i = 1; i <= 8; ++i){ scanf("%d%d%d",&s[i][1],&s[i][2],&s[i][3]); } flag = false; Dfs(1); if(!flag) printf("NO\n"); return 0; }
C题:思维。
题意:对于一个10^5长的串(每一位都是'0'~'9'),每次操作会将1种字母换成1种子串,操作最多10^5个。问最后的答案mod(1e9+7)是几。
思路:比赛没搞出来... 因为正着想实在是烦,虽然想到保存每个数字最后的值和位数,但是不好算。
方法是:倒过来进行操作,保存每个数字最后对应的串 mod 之后的值以及其位数。
(这里算位数是要用于计算10的幂,由于指数很大,可以将指数 mod (1e9+7 - 1) 来加速,原理:指数循环节。当然也可以不用保存位数,而直接保存10的幂。)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int mod = 1e9 + 7; char s[100010]; string tmp[100010]; int n; int val[11]; ll len[11]; int Q_pow(int x,int y){ int ans = 1; while(y){ if(y & 1) ans = 1ll * ans * x % mod; x = 1ll * x * x % mod; y >>= 1; } return ans; } int main(){ scanf("%s",s + 1); scanf("%d",&n); for(int o = 1; o <= n; ++o) cin >> tmp[o]; for(int i = 0; i < 10; ++i) len[i] = 1,val[i] = i; for(int o = n; o >= 1; --o){ int id = tmp[o][0] - '0'; int tval = 0; ll tlen = 0; for(int i = 3; i < tmp[o].size(); ++i){ int pos = tmp[o][i] - '0'; tval = (1ll * tval * Q_pow(10,len[pos]) % mod + val[pos]) % mod; tlen += len[pos]; } val[id] = tval; len[id] = tlen % (mod - 1); } int ans = 0; ll tlen = 0; for(int i = 1; s[i]; ++i){ ans = (1ll * ans * Q_pow(10,len[s[i] - '0']) % mod + val[s[i] - '0']) % mod; } printf("%d\n",ans); return 0; }