Fang Fang
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 871 Accepted Submission(s): 364
I promise her. We define the sequence F of strings.
F0 = ‘‘f",
F1 = ‘‘ff",
F2 = ‘‘cff",
Fn = Fn−1 + ‘‘f", for n > 2
Write down a serenade as a lowercase string S in a circle, in a loop that never ends.
Spell the serenade using the minimum number of strings in F , or nothing could be done but put her away in cold wilderness.
Following are T lines, each line contains an string S as introduced above.
The total length of strings for all test cases would not be larger than 106 .
For each test case, if one can not spell the serenade by using the strings in F , output −1 . Otherwise, output the minimum number of strings in F to split S according to aforementioned rules. Repetitive strings should be counted repeatedly.
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;
}
【1010】 Jesus Is Here (斐波那契+推公式)
Jesus Is Here
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 360 Accepted Submission(s): 255
``But Jesus is here!" the priest intoned. ``Show me your messages."
Fine, the first message is s1=‘‘c" and the second one is s2=‘‘ff" .
The i -th message is si=si−2+si−1 afterwards. Let me give you some examples.
s3=‘‘cff" , s4=‘‘ffcff" and s5=‘‘cffffcff" .
``I found the i -th message's utterly charming," Jesus said.
``Look at the fifth message". s5=‘‘cffffcff" and two ‘‘cff" appear in it.
The distance between the first ‘‘cff" and the second one we said, is 5 .
``You are right, my friend," Jesus said. ``Love is patient, love is kind.
It does not envy, it does not boast, it is not proud. It does not dishonor others, it is not self-seeking, it is not easily angered, it keeps no record of wrongs.
Love does not delight in evil but rejoices with the truth.
It always protects, always trusts, always hopes, always perseveres."
Listen - look at him in the eye. I will find you, and count the sum of distance between each two different ‘‘cff" as substrings of the message.
Following T lines, each line contain an integer n (3≤n≤201314) , as the identifier of message.
Each line contains an integer equaling to:
where sn as a string corresponding to the n -th message.
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;
}
Largest Point
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1005 Accepted Submission(s): 397
For each test case, the first line contains three integers corresponding to n (2≤n≤5×106), a (0≤|a|≤106) and b (0≤|b|≤106) . The second line contains n integers t1,t2,⋯,tn where 0≤|ti|≤106 for 1≤i≤n .
The sum of n for all cases would not be larger than 5×106 .
For each test case, you should output the maximum value of at2i+btj .
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;
}
Minimum Cut
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 860 Accepted Submission(s): 372
We say that a cut in G respects T if it cuts just one edges of T .
Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph G respecting the given spanning tree T .
The first line of the input is a single integer t (1≤t≤5) which is the number of test cases.
Then t test cases follow.
Each test case contains several lines.
The first line contains two integers n (2≤n≤20000) and m (n−1≤m≤200000) .
The following n−1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge.
Next m−n+1 lines describe the undirected graph G and each of them contains two integers u and v corresponding to an edge which is not in the spanning tree T .
1 4 5 1 2 2 3 3 4 1 3 1 4
Case #1: 2
建图方法是先建T树 然后再T树上加m-n+1条边构成G图
在树上每加一条边u,v u跟v的不同子树间都连一条边 也就是u,v一直向上到LCA(u,v)度数++ 这样找最小度数的节点就行 可惜当时渣到不会LCA 有个板子也好……
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int MAXN = 81000;//点数的最大值
const int MAXM = 604000;//边数的最大值
int rmq[2*MAXN];//rmq数组,就是欧拉序列对应的深度序列
struct ST
{
int mm[2*MAXN];
int dp[2*MAXN][20];//最小值对应的下标
void init(int n)
{
mm[0] = -1;
for(int i = 1;i <= n;i++)
{
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = i;
}
for(int j = 1; j <= mm[n];j++)
for(int i = 1; i + (1<<j) - 1 <= n; i++)
dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
}
int query(int a,int b)//查询[a,b]之间最小值的下标
{
if(a > b)swap(a,b);
int k = mm[b-a+1];
return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
}
};
struct Edge
{
int v,next;
};
Edge eg[MAXM];
int head[MAXN],tp;
int cnt;
int len[MAXN],fa[MAXN];
int P[MAXN];//P[i]表示点i在F中第一次出现的位置
int F[MAXN*2];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
ST st;
void dfs(int u,int pre,int dep)
{
fa[u]=pre;
F[++cnt] = u;
rmq[cnt] = dep;
P[u] = cnt;
for(int i = head[u];i != -1;i = eg[i].next)
{
int v = eg[i].v;
if(v == pre)continue;
dfs(v,u,dep+1);
F[++cnt] = u;
rmq[cnt] = dep;
}
}
void LCA_init(int root,int node_num)//查询LCA前的初始化
{
cnt = 0;
dfs(root,root,0);
st.init(2*node_num-1);
}
int query_lca(int u,int v)//查询u,v的lca编号
{
return F[st.query(P[u],P[v])];
}
void Add(int u,int v)
{
eg[tp].v = v;
eg[tp].next = head[u];
head[u] = tp++;
}
int dp[MAXN];
void cal(int u,int pre)//搜最小度数
{
for(int i = head[u]; ~i; i = eg[i].next)
{
int v = eg[i].v;
if(v == pre) continue;
cal(v,u);
dp[u] += dp[v];
}
}
int main()
{
int t,n,u,v,m,ans;
scanf("%d",&t);
for(int z = 1; z <= t; ++z)
{
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
tp = 0;
for(int i = 0; i < n-1; ++i)
{
scanf("%d %d",&u,&v);
Add(u,v);
Add(v,u);
}
LCA_init(1,n);
memset(dp,0,sizeof(dp));
for(int i = n; i <= m; ++i)
{
scanf("%d %d",&u,&v);
dp[u]++;
dp[v]++;
dp[query_lca(u,v)] -= 2;
}
cal(1,0);
ans = INF;
for(int i = 2; i <= n; ++i)
ans = min(ans,dp[i]+1);
printf("Case #%d: %d\n",z,ans);
}
return 0;
}