BestCoder_R74div2===补题

来源:互联网 发布:淘宝买家中心在哪里 编辑:程序博客网 时间:2024/06/06 17:36

参考:http://blog.csdn.net/lych_cys/article/details/50810893

T1:LCP Array

       题意:已知一个字符串相邻两个后缀(指下标相邻)的最长共同前缀,求可行的字符串个数。

下面a数组表示输入的最长公共前缀。s数组表示字符串。

       如果a[i]>0,那么就有s[i]=s[i+1]。可以推出必有a[i]=a[i+1]+1或者a[i]=0,这样就可以判断无解输出0了。另一方面,我们发现s[1]有26种取法,另外如果s[i]!=s[i+1]那么s[i+1]有25种取法否则有1种取法。那么用乘法原理累乘起来就好了。

隐藏信息:字符串的最后一个字符的往后是没有公共前缀的,所以a[N]是0,这个可以方便后面代码的书写。

       时间复杂度O(N)。

#include<iostream>#include<cstring>#include<cstdio>using namespace std;typedef long long LL;const int maxn = 1000000;int a[maxn];int main() {//freopen("C:\\Users\\czkct\\Desktop\\LCP.txt", "r", stdin);//freopen("C:\\Users\\czkct\\Desktop\\ANS.txt", "w", stdout);int T;cin >> T;while(T--) {int N;cin >> N;for(int i = 1; i < N; i++)cin >> a[i];a[N] = 0;LL ans = 26;for(int i = N-1; i ; i--) {if(!a[i])  ans = ans*25%1000000007;else if(a[i] != a[i+1] + 1) {ans = 0;break;} }cout << ans << endl;}return 0;}

注意:

 这个ans的类型不能是int型(之前在这儿wa了很多次), 因为当ans的结果很接近1000000007但又比它小时,突然又乘上一个25的话就会马上超出int型范围导致溢出,所以用longlong型。


(我是在是不会写   ,把大神的差不多直接copy过来了, 代码加了一番注释)

 T2:Shortest Path     (看完大神的代码我就在想,为何大神的代码思路如此清晰。。而我的....哭诶。。。。 )

       题意:一开始所有点都在一条链上,满足dist(i,i+1)=1,现在加入三条边(i,j)且dist(i,j)=1,求s-t的最短路。多组询问。

       显然s-t一定是从s出发,走过若干个新加的边,最后到达t。那么可以用dfs枚举新加入的三条边(i,j)加入的顺序,加入时需要枚举方向,然后再求最短路就行了。

       时间复杂度O(MN!2^N),其中N=3。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#define mod 1000000007#define ll long long using namespace std;int n, m, ans, x, y, a[10][2]; bool bo[10]; void dfs(int k, int now, int d) {if(d+abs(now-y) < ans) ans = d + abs(now-y);if(k > 3) return ;for(int i; i <= 3; i++) if(bo[i]) {  bo[i] = 0;//用这个标识是因为新增的三条路,每条路在一次询问里面最多智能走一遍。 dfs(k+1, a[i][1], d+abs(now-a[i][0])+1 );  //每一条路都有两种通过方式 dfs(k+1, a[i][0], d+abs(now-a[i][1])+1 );  bo[i] = 1;}}int main() {int cas; cin >> cas;while(cas--) {cin >> n >> m; int i;for(i = 1; i <= 3; i++) cin >> a[i][0] >> a[i][1]; //a[i][0]表示新添加的路的左边的那个点 , a[i][1]表示右边的那个点memset(bo, 1, sizeof(bo)); ll sum = 0;  //初始化结果 for(i = 1; i <= m; i++) {cin >> x >> y;ans = abs(y-x); //简单粗暴的直线距离dfs(1, x, 0);//以x为起点开始搜索最短路  第一个参数代表枚举过程(不超过三个过程,//每个过程选一条路,第二个参数是当前起点,第三个参数是已走路程)  sum = (sum+(ll)ans*i)%mod;   } printf("%I64d\n", sum);}}

上面的这个代码会超时!!!!

 超时原因:输入输出, cin、cout太慢了  10^5的询问   量太大, 用cin、cinout  TLE  time:2000ms,      用scanf、printf、 AC  time:1950ms, 擦边过

还是得下面的这个 , 大神原先写的:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#define ll long long #define mod 1000000007using namespace std;int n, m, x, y, ans, a[4][2], bo[4];void dfs(int k, int now, int d) {if(d+abs(now-y) < ans) ans = d+abs(now-y);if(k > 3) return ;for(int i = 1; i<= 3; i++) if(bo[i]) {bo[i] = 0; dfs(k+1, a[i][1], d+abs(now-a[i][0])+1);dfs(k+1, a[i][0], d+abs(now-a[i][1])+1);bo[i] = 1;}}//1950ms int main() {int cas;cin >> cas;while(cas--) {scanf("%d%d", &n, &m);for(int i = 1; i <= 3; i++) scanf("%d%d", &a[i][0], &a[i][1]);ll sum = 0;for(int i = 1; i <= m; i++) {scanf("%d%d", &x, &y);memset(bo, 1, sizeof(bo));ans = abs(x-y); //直接距离dfs(1, x, 0);sum = (sum+(ll)ans*i)%mod;}printf("%I64d\n", sum);}return 0;}/*  2000msint main() {int cas;cin >> cas;while(cas--) {cin >> n >> m;for(int i = 1; i <= 3; i++) cin >> a[i][0] >> a[i][1];ll sum = 0;for(int i = 1; i <= m; i++) {cin >> x >> y;memset(bo, 1, sizeof(bo));ans = abs(x-y); //直接距离dfs(1, x, 0);sum = (sum+(ll)ans*i)%mod;}cout << sum << endl;}return 0;}*/


0 0
原创粉丝点击