2014.10.25 训练,和一个队友做cf上的gym的比赛,过了6题。
感觉还可以,有几道水题没有卡住,一道模拟,一道贪心,一道高精度+推公式
剩下的,一道kmp(非裸题),一道dfs搜索,一道数学期望
还有一道G题看了没做,问了学长,是一个环连着多个树,然后dp.. 没弄出来。感觉这个姿势很神奇
G I J 已经被我亮星了,改天过了,再更新本博文
已过题目:ACDEFHK
待过题目:GIJ
感觉过不了的题目(=。=!):BF
这题还是很简单的。
每个点要不然有登机口,要不然没有。
对于一个联通图,如果一个点确定了是否有登机口,那么这个联通图中的所有点都可以确定是否有登机口。
对于每个联通图,dfs搜索,假设起点有和没有两种情况来搜。
要分情况讨论,注意impossible成立的条件。
这里细讲太过于冗杂,就不陈述了。代码如下:
(dfs不太好写)
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 200100
#define N
#define M
int n,m,a,b,c;
struct Edge
{
int from,to,next;
int val;
}edge[2*MAXN];
int head[MAXN],w;
void add_edge(int from,int to,int val){
w++;
edge[w].from=from;
edge[w].to=to;
edge[w].val=val;
edge[w].next=head[from];
head[from]=w;
}
bool vis1[MAXN],vis2[MAXN],must[MAXN];
void dfs(int now,bool *vis,int &anst){
vis[now]=true;
if(must[now]) anst+=1;
int i,to,val;
for(i=head[now];i!=-1;i=edge[i].next){
to=edge[i].to;
val=edge[i].val;
if(vis[to]){
if(must[now]&&val==0){
anst=-1;
return;
}
else if(must[now]&&val==1&&must[to]){
anst=-1;
return;
}
else if(must[now]&&val==2&&!must[to]){
anst=-1;
return;
}
else if(!must[now]&&val==0&&must[to]){
anst=-1;
return;
}
else if(!must[now]&&val==1&&!must[to]){
anst=-1;
return;
}
else if(!must[now]&&val==2){
anst=-1;
return;
}
}
else{//vis[to]=false;
if(must[now]&&val==0){
anst=-1;
return;
}
else if(must[now]&&val==1){
must[to]=false;
dfs(to,vis,anst);
}
else if(must[now]&&val==2){
must[to]=true;
dfs(to,vis,anst);
}
else if(!must[now]&&val==0){
must[to]=false;
dfs(to,vis,anst);
}
else if(!must[now]&&val==1){
must[to]=true;
dfs(to,vis,anst);
}
else if(!must[now]&&val==2){
anst=-1;
return;
}
if(anst==-1) return;
}
}
}
int main()
{
cin>>n>>m;
repin(i,1,n){
head[i]=-1;
vis1[i]=false;
vis2[i]=false;
}
w=0;
repin(i,1,m){
scanf("%d %d %d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
}
int ans=0,anst1,anst2;
repin(i,1,n){
if(vis1[i] || vis2[i]) continue;
must[i]=true;
anst1=0;
dfs(i,vis1,anst1);
must[i]=false;
anst2=0;
dfs(i,vis2,anst2);
if(anst1==-1&&anst2==-1){
printf("impossible\n");
exit(0);
}
else if(anst1!=-1&&anst2==-1){
ans+=anst1;
}
else if(anst1==-1&&anst2!=-1){
ans+=anst2;
}
else ans+=min(anst1,anst2);
}
printf("%d\n",ans);
}
这题也不单单是高精度问题,需要将公式推出来
不难发现,Sn=C(n+1),然后求C(n)题目已经给了个公式C(n)=(2n,n)/(n+1);
(2n,n)就是排列组合中的组合问题,即2n个里选n个的总数,那么求(2n,n)复杂度就是O(n)的了
接下来就是用高精度来做,模拟下就出来了。
一开始我的思路是把每一个C(n)求出来,再求S(n),用java做T了
下面java7过的代码,c++高精度模版我还没有,以后要搞一个自己的
import java.io.*;
import java.util.*;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) throws Exception {
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
BigInteger up,down;
up=down=new BigInteger("1");
BigInteger tt=new BigInteger((2*n+2)+"");
BigInteger one=new BigInteger("1");
for(int i=1;i<=n+1;i++){
BigInteger t=new BigInteger(i+"");
down=down.multiply(t);
up=up.multiply(tt);
tt=tt.subtract(one);
}
BigInteger ans=up.divide(down);
BigInteger t1=new BigInteger((n+2)+"");
ans=ans.divide(t1);
System.out.println(ans);
}
}
这题就是求期望分数
期望分数=所有的 (分数*该分数占的概率)
原谅我偷懒不写出数学公式来了0.0
最后判断浮点相等别忘了eps
代码如下:
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M 1000
int a1,b1,a2,b2,n1,n2;
int number1[M],number2[M];
double avepoint1,avepoint2;
int dcmp(double x){
if(fabs(x)<eps) return 0;
else if(x<0) return -1;
else return 1;
}
int main()
{
cin>>a1>>b1>>a2>>b2;
repin(i,a1,b1){
repin(j,a2,b2){
number1[i+j]+=1;
}
}
n1=(b1-a1+1)*(b2-a2+1);
avepoint1=0.0;
repin(i,a1+a2,b1+b2){
double t=(double)1.0*number1[i]/n1;
avepoint1+=t*i;
}
cin>>a1>>b1>>a2>>b2;
repin(i,a1,b1){
repin(j,a2,b2){
number2[i+j]+=1;
}
}
n2=(b1-a1+1)*(b2-a2+1);
avepoint2=0.0;
repin(i,a1+a2,b1+b2){
double t=(double)1.0*number2[i]/n2;
avepoint2+=t*i;
}
int t=dcmp(avepoint1-avepoint2);
if(t==0) printf("Tie\n");
else if(t<0) printf("Emma\n");
else printf("Gunnar\n");
}
这题是贪心问题。
我不知道为什么是对的,和队友讨论了后,得出了个结论,但没有严格证明,没有图也不好说,就不陈述了。
将数列从小到大排序,从后往前扫,假设这个点左边全部用横向消除方法,右边全部用纵向消除方法
每次左边和右边的方法都可以知道需要多少步,维护最小值即可
代码如下:
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M 1000
int n,ans;
int h[MAXN];
int main()
{
cin>>n;
repin(i,1,n){
scanf("%d",h+i);
}
sort(h+1,h+1+n);
ans=n;
depin(i,n,1){
int t=h[i]+(n-i);
ans=min(ans,t);
}
cout<<ans<<endl;
}
给两个时钟,每个时钟有n个指针,方向散乱无序,告诉你12点钟方向顺时针转到该指针的角度是多少
问,将第一个时钟旋转某个角度,是否可以和第二个时钟完全重合?
只需要输出是否即可,不需要知道旋转多少度
思路如下
将2个时钟指针角度都从小到大排序
每个时钟求出下一个指针和上一个指针的角度差,构成2个数组(注意这个过程末尾和第一个指针构成的角度)
现在需要做的是,判断下一个数组头尾移动后,能否和第一个数组重合。
将第一个数组复制一遍,从n长度,变成2n,d1[i+n]==d[i]
那么,问题就变成了,下面这个长度为n的数组,是否是上面那个长度为2n数组的子串
跑一发kmp就出来了
代码如下:
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 200100
#define N
#define M
int n;
int a[MAXN],b[MAXN];
int d1[2*MAXN],d2[MAXN];
int nextpos[MAXN];
void Build_nextpos(){
int i,j;
i=0;
nextpos[0]=j=-1;
while(i<n){
if(j==-1 || d2[i]==d2[j]){
nextpos[i+1]=j+1;
if(d2[j+1]==d2[i+1]) nextpos[i+1]=nextpos[j+1];
i++;
j=j+1;
}
else j=nextpos[j];
}
}
bool kmp(){
int i,j;
i=j=0;
while(i<2*n && j<n){
if(j==-1 || d1[i]==d2[j]){
i++;
j++;
}
else j=nextpos[j];
}
if(j==n) return true;
else return false;
}
int main()
{
cin>>n;
rep(i,0,n){
scanf("%d",a+i);
}
sort(a,a+n);
rep(i,0,n){
scanf("%d",b+i);
}
sort(b,b+n);
rep(i,0,n){
if(i==n-1) d1[i]=360000-a[i]+a[0];
else d1[i]=a[i+1]-a[i];
}
rep(i,n,2*n){
d1[i]=d1[i-n];
}
rep(i,0,n){
if(i==n-1) d2[i]=360000-b[i]+b[0];
else d2[i]=b[i+1]-b[i];
}
Build_nextpos();
if(kmp()) printf("possible\n");
else printf("impossible\n");
}
简单模拟题
判断火车人数是否小于0
判断火车人数是否超过限制
判断火车是否存在人没满但却有人等待的情况
判断最终火车是否为空
代码如下:
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M 1000
int c,n,nowcapacity;
void impossible(){
printf("impossible\n");
exit(0);
}
int main()
{
cin>>c>>n;
nowcapacity=0;
int out,in,wait;
repin(i,1,n){
scanf("%d %d %d",&out,&in,&wait);
nowcapacity-=out;
if(nowcapacity<0) impossible();
nowcapacity+=in;
if(nowcapacity>c) impossible();
if(nowcapacity!=c && wait!=0) impossible();
}
if(nowcapacity!=0) impossible();
printf("possible\n");
}