8 ffcfffcffcff cffcfff cffcff cffcf ffffcffcfff cffcfffcffffcfffff cff cffc
Case #1: 3 Case #2: 2 Case #3: 2 Case #4: -1 Case #5: 2 Case #6: 4 Case #7: 1 Case #8: -1HintShift the string in the first test case, we will get the string "cffffcfffcff" and it can be split into "cffff", "cfff" and "cff".
题意是找最小的划分 子串在题中已给出 f ff cff cfff cf4 cf5 cf6 cfn 这样只要暴力判两个c之间f的数目即可 如果存在两个c之间f小于2 说明不可划分 否则一定会划分成c的数量个区间 也就是划分的最小数量为c的数量 另外 如果没c 就划分成len/2+len%2 即全划ff或f
额外需要注意的是有空串和其余字符还有串是环串 首尾连在一起的。。。
代码如下:
#include <bits/stdc++.h> using namespace std; char str[1111111]; int pos[1111111]; int tp; int main() { int t,i,z,cnt,f,len; scanf("%d",&t); getchar(); for(z = 1; z <= t; ++z) { gets(str); tp = 0; f = 1; for(i = 0; str[i]; ++i) { if(str[i] == 'c') pos[tp++] = i;//记录每个c的位置 else if(str[i] != 'f') f = 0;//有其余字符 } len = strlen(str); printf("Case #%d: ",z); if(!f) puts("-1");//有其余字符 else if(tp == 0)//没有c { printf("%d\n",len/2+len%2); } else { for(i = 0; i < tp-1; ++i) { if(pos[i+1]-pos[i]-1 < 2)//两个c之间f数量小于2 { f = 0; break; } } if(len-1-pos[tp-1]+pos[0] < 2) f = 0;//特判第一个c和最后一个 因为是成环切割 if(f) { printf("%d\n",tp); }else puts("-1"); } } return 0; }
9 5 6 7 8 113 1205 199312 199401 201314
Case #1: 5 Case #2: 16 Case #3: 88 Case #4: 352 Case #5: 318505405 Case #6: 391786781 Case #7: 133875314 Case #8: 83347132 Case #9: 16520782
首先有这么几个数组
pre //首个c到之后c的距离和
post //最后一个c到之前c的距离和
cnt //点数
ans //答案(任意两个c距离和)
f //最大两个c的间距
1 c
2 ff
3 cff
4 ffcff
5 cffffcff
6 ffcffcffffcff
7 cffffcffffcffcffffcff
这是前几项 很容易推出
cnt[i] = cnt[i-2] + cnt[i-1] //点数
f[i] = f[i-2] + f[i-1] + ((i%2 == 0)? 3: 5) //c 最大间距
然后发现 如果有pre 跟post之后 ans也可推出
ans[i] = post[i-2]*cnt[i-1]+pre[i-1]*cnt[i-2]+x*cnt[i-2]*cnt[i-1]+ans[i-1]+ans[i-2]; // x :两串合并后中间cffffc f数量 跟当前串奇偶有关 x = ((i%2 == 0)? 3: 5)
ans = 前串末c到之前所有c的距离和 * 后串c个数 + 后串首c到之后所有c的距离和*前串c的个数 + 中间f数量*两串c数积 + 两串各自c距离和
原理: 组成新串后 后串任意c到前串每个c的距离等于 前串末c到之前每个c距离+生成新串中间新加f数*前串点数
前串c到后串同理 之后再加上两串各自c距离和即可
这样只需要再推出pre跟post即可
pre[i] = x*cnt[i-1]+pre[i-1]+pre[i-2]+f[i-2]*cnt[i-1] //新串首c到之后c的距离和 继承前后串距离和-pre[i-2,i-1] 然后到后串经过 cnt[i-1]*f[i-2] 和 x*cnt[i-1]
post[i] = x*cnt[i-2]+post[i-1]+post[i-2]+f[i-1]*cnt[i-2] //同上
递推结束 O(1)输出答案即可 注意推到过程中步步取余。。烦= =
代码如下:
#include <bits/stdc++.h> #define mod 530600414 #define ll long long using namespace std; ll f[201316]; ll cnt[201316]; ll ans[201316],pre[201316],post[201316]; int main() { int i,t,n,x; cnt[3] = 1; cnt[4] = 1; f[3] = 0; f[4] = 0; ans[3] = ans[4] = 0; pre[3] = pre[4] = post[3] = post[4] = 0; for(i = 5; i <= 201314; ++i) { cnt[i] = (cnt[i-1]+cnt[i-2])%mod; <span style="white-space:pre"> </span>x = i&1? 5: 3; f[i] = (f[i-1]+f[i-2]+x)%mod; pre[i] = (((x*cnt[i-1]%mod+pre[i-1])%mod+pre[i-2])%mod+f[i-2]*cnt[i-1]%mod)%mod; post[i] = (((x*cnt[i-2]%mod+post[i-1])%mod+post[i-2])%mod+f[i-1]*cnt[i-2]%mod)%mod; ans[i] = (((post[i-2]*cnt[i-1]%mod+pre[i-1]*cnt[i-2]%mod)%mod+x*cnt[i-2]*cnt[i-1]%mod)%mod+ans[i-1]+ans[i-2])%mod; } scanf("%d",&t); for(int z = 1; z <= t; ++z) { scanf("%d",&n); printf("Case #%d: %I64d\n",z,ans[n]); } return 0; }
2 3 2 1 1 2 3 5 -1 0 -3 -3 0 3 3
Case #1: 20 Case #2: 0
两数组排序后直接去第一个判断下标是否一样 一样就比较a取最大*b取次大跟a取次打b最大 输出最大即可
我做的是不断判断。。。
算是个教训 两种都贴上吧
代码如下:
//渣法。。四个判断。。。 #include <bits/stdc++.h> #define ll long long #define mx 2000000 #define fwrite() freopen("../out.out","r",stdout) #define fread() freopen("../in.in","w",stdin) using namespace std; ll a,b; vector <ll> v; ll gt(ll t1,ll t2) { return a*t1*t1+b*t2; } int main() { //fread(); //fwrite(); int n,i,t,sz,z; vector<ll>::iterator it,tmp; ll t1,t2,x,ans; scanf("%d",&t); for(z = 1; z <= t; ++z) { v.clear(); scanf("%d %I64d %I64d",&n,&a,&b); for(i = 0; i < n; ++i) { scanf("%I64d",&x); v.push_back(x); } sort(v.begin(),v.end()); it = lower_bound(v.begin(),v.end(),0); sz = v.size(); if(a < 0 && b < 0)//- - { tmp = it; tmp--; if(it == v.begin() || tmp == v.begin()) { ans = max(gt(v[1],v[0]),gt(v[0],v[1])); } else ans = max(gt(*it,v[0]),gt(*tmp,v[0])); } else if(a < 0 && b >= 0)//- + { tmp = it; tmp++; if(tmp == v.end()) { ans = max(gt(v[sz-1],v[sz-2]),gt(v[sz-2],v[sz-1])); } else if(it == v.begin()) { ans = gt(v[0],v[sz-1]); } else { tmp = it--; ans = max(gt(*it,v[sz-1]),gt(*tmp,v[sz-1])); } } else if(a >= 0 && b <= 0)//+ - { ans = max(gt(v[0],v[1]),gt(v[sz-1],v[0])); } else//+ + { ans = gt(v[0],v[sz-1]); ans = max(ans,gt(v[sz-1],v[sz-2])); ans = max(ans,gt(v[sz-2],v[sz-1])); } printf("Case #%d: %I64d\n",z,ans); } return 0; }
//排序输出。。。慢 慢又怎样 好想啊…………if渣法卡半天TOT #include <bits/stdc++.h> #define ll long long #define mx 2000000 #define fwrite() freopen("../out.out","r",stdout) #define fread() freopen("../in.in","w",stdin) using namespace std; struct Mult { ll ans; int id; bool operator < (const struct Mult a)const { return ans == a.ans? id < a.id : ans > a.ans; } }; Mult mla[6666666],mlb[6666666]; ll a,b; int main() { //fread(); //fwrite(); int n,i,t,z; ll x; scanf("%d",&t); for(z = 1; z <= t; ++z) { scanf("%d %I64d %I64d",&n,&a,&b); for(i = 0; i < n; ++i) { scanf("%I64d",&x); mla[i].ans = a*x*x; mlb[i].ans = b*x; mla[i].id = mlb[i].id = i; } sort(mla,mla+n); sort(mlb,mlb+n); printf("Case #%d: %I64d\n",z,mla[0].id != mlb[0].id? (mla[0].ans+mlb[0].ans): max(mla[0].ans+mlb[1].ans,mla[1].ans+mlb[0].ans)); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
【题解】 2015 ACM/ICPC Asia Regional Shenyang Online
原文:http://blog.csdn.net/challengerrumble/article/details/48706295