这把打得真是水,简直不能忍,题数就差了2题,木有出线,我要背锅。。
1012 Largest Point
这题我并没有码,讲讲思路就好了。要求一个式子最大值,分析一下发现可以贪心搞,把最大2个数、最小2个数、绝对值最小2个数找出来,注意不用sort,然后暴力试这6个数就好了。学弟很给力1A了。
1006 Fang Fang
如果字符串中全是f,那么就是(len+1)/2。如果是c和f,随便把一个c循环到开头,检查两个c之间和最后一个c到末尾的f是否达到2个以上。然而我写了bug坑了几发。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
#include <string.h>
#include <queue>
#include <map>
using namespace std;
#define ll long long
char str[1000010];
char str2[1000010];
int main(){
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
scanf("%s",str);
int len=strlen(str);
int firstC=-1;
for(int i=0;i<len;i++){
if(str[i]=='c'){
firstC=i;
break;
}
}
printf("Case #%d: ",cas);
bool woca=0;
for(int i=0;i<len;i++){
if(str[i]!='c'&&str[i]!='f'){
woca=1;break;
}
}
if(woca){
printf("-1\n");
continue;
}
if(firstC==-1){
printf("%d\n",(len+1)>>1);
}else{
for(int i=firstC;i<len;i++){
str2[i-firstC]=str[i];
}
for(int i=0;i<firstC;i++){
str2[i+len-firstC]=str[i];
}
bool ok=1;
int cnt=0;
int ans=0;
for(int i=1;i<=len;i++){
if(str2[i]=='c'||i==len){
if(cnt<2){
ok=0;break;
}
cnt=0;
ans++;
}else{
cnt++;
}
}
if(ok){
printf("%d\n",ans);
}else{
printf("-1\n");
}
}
}
return 0;
}
1010 Jesus Is Here
这题怎么看怎么像斐波那契数,但是解法却无关。从小到大,递推(可以理解为dp)求出每个串有多少个c,第一个c离左边多少,最后一个c离右边多少,还有长度。si很自然地就是si-2和si-1拼起来,答案就是左半部分的答案ans(i-2)+右半部分的答案ans(i-1)+横跨两边的组数,用递推出来的信息算一下就好了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
#include <string.h>
#include <queue>
#include <map>
using namespace std;
#define ll long long
const int maxn = 201320;
const ll mod = 530600414;
ll tol[maxn];
ll tor[maxn];
ll cnt[maxn];
ll ans[maxn];
ll len[maxn];
int main(){
int t;
cin>>t;
int cas=0;
int n;
tol[3]=1; tor[3]=3; cnt[3]=1; len[3]=3;
tol[4]=3; tor[4]=3; cnt[4]=1; len[4]=5;
//
//ans[3]=1; ans[4]=1;
for(int i=5;i<=201314;i++){
cnt[i]=cnt[i-2]+cnt[i-1];
cnt[i]%=mod;
tol[i]=tol[i-2]+tol[i-1]+cnt[i-1]*len[i-2];
tol[i]%=mod;
tor[i]=tor[i-1]+tor[i-2]+cnt[i-2]*len[i-1];
tor[i]%=mod;
len[i]=len[i-2]+len[i-1];
len[i]%=mod;
//
ans[i]=ans[i-1]+ans[i-2];
ans[i]+=tor[i-2]*cnt[i-1];
ans[i]+=tol[i-1]*cnt[i-2];
ans[i]%=mod;
ll tmp = cnt[i-2]*cnt[i-1];
tmp%=mod;
ans[i]+=mod;
ans[i]-=tmp;
ans[i]%=mod;
}
ans[3]=1; ans[4]=1;
while(t--){
cas++;
scanf("%d",&n);
printf("Case #%d: %I64d\n",cas,ans[n]);
}
return 0;
}
1003 Minimum Cut
求一个无向图的最小割,必须恰好包含给出的生成树的一条边。做法是以生成树为骨架,多出来边uv,就把u-v在生成树上的路径上所有边加上权1,到最后最小边权就是答案。用离线LCA算法+打标实现。到最后dfs一次读取标记的信息,得到每条边的权,找出最小值即可。唉,这个处理方法前几天CF做过的,而且是自己想出的,比赛时居然卡题了,逗比如我。。。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
#include <string.h>
using namespace std;
#define ll long long
const int mod=1000000007;
ll INF=1000000000000000000LL;
#define maxn 20010
//输入挂
void scanf_(int &num){
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-')
{
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
}
int n,m;
int tote;
int a[maxn];
int b[maxn];
int res[maxn];
int cnt[maxn];
int head[maxn];
int pre[maxn<<1];
int to[maxn<<1];
void add(int x,int y){
to[tote]=y;
pre[tote]=head[x];
head[x]=tote++;
}
bool vis[maxn];
int ans;
//这个dfs为了读取标记信息。
void dfs2(int k){
vis[k]=1;
cnt[k]+=res[k];
for(int i=head[k];~i;i=pre[i]){
int x=to[i];
if(vis[x])continue;
dfs2(x);
cnt[k]+=cnt[x];
}
if(k!=1)ans=min(ans,cnt[k]);
}
int ff[maxn];
int _find(int u){
if(ff[u]==u)return u;
int res=_find(ff[u]);
return res;
}
void _union(int a,int b){ //把a并到b上
int fa=_find(a);
int fb=_find(b);
ff[a]=b;
}
//询问有关
const int maxm=200010;
int qhead[maxn];
int qpre[maxm<<1];
int qto[maxm<<1];
int totq;
void qadd(int x,int y){
qto[totq]=y;
qpre[totq]=qhead[x];
qhead[x]=totq++;
}
bool finish[maxn];
//离线LCA
void LCA(int u){
vis[u]=1;
for(int i=head[u];~i;i=pre[i]){
int v=to[i];
if(vis[v])continue;
LCA(v);
_union(v,u);
}
finish[u]=1;
//解决关于u的问题。
for(int i=qhead[u];~i;i=qpre[i]){
int v=qto[i];
if(finish[v]){
int lca=_find(v);
if(u!=lca){
res[u]++;
res[lca]--;
}
if(v!=lca){
res[v]++;
res[lca]--;
}
}
}
}
void init(){
memset(head,-1,sizeof(head));
memset(cnt,0,sizeof(cnt));
memset(res,0,sizeof(res));
memset(finish,0,sizeof(finish));
memset(qhead,-1,sizeof(qhead));
memset(vis,0,sizeof(vis));
tote=0;
totq=0;
//
for(int i=1;i<=n;i++){
ff[i]=i;
}
}
int main(){
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
cin>>n>>m;
init();
for(int i=1;i<n;i++){
scanf_(a[i]);
scanf_(b[i]);
add(a[i],b[i]);
add(b[i],a[i]);
}
ans=1000000000;
for(int i=n;i<=m;i++){
int a,b;
scanf_(a);
scanf_(b);
qadd(a,b);
qadd(b,a);
}
memset(vis,0,sizeof(vis));
LCA(1);
memset(vis,0,sizeof(vis));
dfs2(1);
printf("Case #%d: ",cas);
cout<<ans+1<<endl;
}
return 0;
}
1002 Best Solver
这题待补。。