【持续更新】CDOJ刷题之路 (UESTC) ___ 完成于20130522

快省选了,在UESTC上刷一下题,熟悉一下出题风格


题库地址:http://acm.uestc.edu.cn/problems.php




1000 A+B Problem

这个还用解释?



1001 DotNotation

很好的一道模拟题,细节很多  http://blog.csdn.net/jiangzh7/article/details/8921285

#include<cstdio>
#include<cstring>
char s[100];

inline bool isnum(char ch)
{
	if(ch>='0' && ch<='9') return 1;
	return 0;
}
inline bool isop(char ch)
{
	if(ch=='+'||ch=='-') return 1;
	if(ch=='*'||ch=='/') return 1;
	return 0;
}

int solve()
{
	scanf("%s",s);
	int len=strlen(s);
	int i=0;
	if(!isnum(s[i=0])) return 0;
	i++;
	while(i<len)
	{
		while(s[i]=='.') i++;
		if(!isop(s[i])) return 0;
		i++;
		while(s[i]=='.') i++;
		if(!isnum(s[i])) return 0;
		i++;
	}
	return 1;
}

int main()
{
	freopen("1001.in","r",stdin);
	freopen("1001.out","w",stdout);
	int t; scanf("%d",&t);
	while(t--)
	{
		if(solve()) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}


1002 解救小Q

很好的一道基础宽搜题,记得用各种memset

#include<cstdio>
#include<cctype>
#include<cstring>
#include<queue>
using std::queue;
const int N=50+10;
const int dx[]={1,-1,0,0};
const int dy[]={0,0,1,-1};

int n,m;
char g[N][N];
struct Point{
	int x,y;
	Point()	{x=-1; y=-1;}
	void init(int a,int b) { x=a; y=b; }
	bool used() 
	{
		return x!=-1 && y!=-1;
	}
}door['z'+10][2];
int sx,sy,tx,ty;
struct Qnode{
	int x,y,step;
	bool operator == (const Qnode &a) const
	{
		return a.x==x && y==a.y;
	}
}start,target;
queue<Qnode> Q;
bool vis[N][N];

void carry(int &x,int &y)
{
	int d=g[x][y]-'a',k=0;
	if(door[d][0].x==x && door[d][0].y==y) k=1;
	x=door[d][k].x; y=door[d][k].y;
}

bool expand(Qnode cur,Qnode &nex,int k)
{
	int x=cur.x+dx[k];
	int y=cur.y+dy[k];
	if(x<0||x>=n||y<0||y>=m) return 0;
	if(g[x][y]=='#') return 0;
	if(isalpha(g[x][y])) carry(x,y);
	nex=(Qnode){x,y,cur.step+1};
	return 1;
}

int bfs()
{
	target=(Qnode){tx,ty,0};
	start=(Qnode){sx,sy,0};
	Q.push(start); vis[sx][sy]=1;
	while(!Q.empty())
	{
		Qnode cur=Q.front();Q.pop();
		Qnode nex;
		//printf("(%d,%d) %d \n",cur.x,cur.y,cur.step);
		for(int k=0;k<4;k++)
		{
			if(!expand(cur,nex,k)) continue;
			if(nex==target) return nex.step;
			if(!vis[nex.x][nex.y])
			{
				vis[nex.x][nex.y]=1;
				Q.push(nex);
			}
		}
	}
	return -1;
}

int solve()
{
	memset(g,0,sizeof(g)

矩阵乘法,不解

); memset(door,-1,sizeof(door)); memset(vis,0,sizeof(vis)); while(!Q.empty()) Q.pop(); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%s",g[i]); for(int j=0;j<m;j++) { if(g[i][j]=='L') sx=i,sy=j,g[i][j]='.'; if(g[i][j]=='Q') tx=i,ty=j,g[i][j]='.'; if(isalpha(g[i][j])) { int k=0, p=g[i][j]-'a'; if(door[p][k].used()) k=1; door[p][k].init(i,j); } } } return bfs(); } int main() { freopen("1002.in","r",stdin); freopen("1002.out","w",stdout); int t; scanf("%d",&t); while(t--) printf("%d\n",solve()); return 0; }



1003 真实的谎言

刚看到题目有点无从下手,其实仔细分析一下

如果说赞成有 x 个人说实话的人有 x 个,那么就表示当前有 x 人说实话【想通就恍然大悟了】

所以枚举一次即可(数据范围不小,但是数据比较弱,暴力枚举就A了,可以线段树优化)

#include<cstdio>
#include<cstring>
const int N=100000+10;
int n,cnt[N];

int solve()
{
	scanf("%d",&n);
	memset(cnt,0,sizeof(cnt));
	for(int i=1;i<=n;i++)
	{
		int a,b; scanf("%d%d",&a,&b);
		for(int j=a;j<=b;j++) cnt[j]++;
	}
	for(int j=n;j>=0;j--)
		if(cnt[j]==j) return j;
	return -1;
}

int main()
{
	freopen("1003.in","r",stdin);
	freopen("1003.out","w",stdout);
	int t; scanf("%d",&t);
	while(t--) printf("%d\n",solve());
	return 0;
}



1004 8球胜负(eight)

不用多说,简单的模拟题

#include<cstdio>
#include<cstring>

int n;
char s[10000];
int red,yel;

void solve()
{
	memset(s,0,sizeof(s));
	scanf("%s",s);
	int len=strlen(s);
	red=yel=0;
	for(int i=0;i<len;i++)
	{
		if(s[i]=='R') red++;
		else if(s[i]=='Y') yel++;
		else if(s[i]=='B')
		{
			if(red==7) printf("Red\n");
			else printf("Yellow\n");
		}
		else if(s[i]=='L')
		{
			if(yel==7) printf("Yellow\n");
			else printf("Red\n");
		}
	}
}

int main()
{
	freopen("1004.in","r",st
    freopen("1366.in","r",stdin);
    freopen("1366.out","w",stdout);din);
	freopen("1004.out","w",stdout);
	while(scanf("%d",&n)==1 && n)
		solve();
	return 0;
}


1005 点球大战(penalty)

模拟题,但是有点坑。。。。名字里面可能含有no,good等,所以用%s的就球了。。。。。每次用fgets读一整行,然后只判断最后是否为no good即可

#include<cstdio>
#include<cstring>

int n;
int map[5][50];

int judge(char *s)//判断最后是否为"no good"
{
	int len=strlen(s);
	int pos=len-1;
	while(s[pos]!=' ') pos--;//找到最后一个空格

( 转载请注明出处.......... http://blog.csdn.net/jiangzh7 ................. By Jiangzh )

s[pos]='\0';//相当于截掉 " good" (有一个空格) int npos=pos-1; while(s[npos]!=' ') npos--;//继续找倒数第二个空格 if(!strcmp(s+npos+1,"no")) return 0; return 1; } void solve() { memset(map,-1,sizeof(map)); int cnt=0,k=2; char s[200]; for(int i=1;i<=n;i++) { memset(s,0,sizeof(s)); fgets(s,200,stdin); int flag=-1; flag=judge(s); if(i&1) cnt++; k=3-k; map[k][cnt]=flag; } for(int i=1;i<=cnt;i++) printf("%d ",i); printf("Score\n"); for(int i=1;i<=2;i++) { int res=0; for(int j=1;j<=cnt;j++) { if(map[i][j]==-1) printf("- "); else if(map[i][j]==0) printf("X "); else if(map[i][j]==1) printf("O "),res++; } printf("%d\n",res); } } int main() { freopen("1005.in","r",stdin); freopen("1005.out","w",stdout); while(scanf("%d\n",&n)==1 && n) solve(); return 0; }     freopen("1256.in","r",stdin);     freopen("1256.out","w",stdout);



中间简单题掠过~

1009虽然出题人说恨水,但是实在无力啊,。。。。。



1025 偏僻的小路

经典的蚂蚁爬杆问题 http://blog.csdn.net/jiangzh7/article/details/8950556

#include<cstdio>

int n,L,v;

int main()
{
	freopen("1025.in","r",stdin);
	freopen("1025.out","w",stdout);
	while(scanf("%d%d%d",&n,&L,&v)==3&&n&&L&&v)
	{
		int sum=0,max=0;
		for(int i=1;i<=n;i++)
		{
			int pos;
			char s[10];scanf("%d%s%s",&pos,s,s);
			if(pos==0 && s[0]=='0') break;
			int leng;
			if(s[0]=='E') leng=L-pos;
			else leng=pos;
			if(leng>max) max=leng;
			sum+=leng;
		}
		printf("%.2lf %d.00\n",(double)max/v,sum);
	}
	return 0;
}




1027 3阶矩阵的乘法

矩阵乘法,不解释。注意输出格式,输出一个矩阵后还有一个回车

#include<cstdio>
#include<cstring>

struct Matrix{
	long long c[4][4];
	void clear() { memset(c,0,sizeof(c)); }
	void Read()
	{
		clear();
		for(int i=1;i<=3;i++)
			for(int j=1;j<=3;j++)
				scanf("%lld",&c[i][j]);
	}
	Matrix operator * (const Matrix &a) const
	{
		Matrix res;res.clear();
		for(int i=1;i<=3;i++)
			for(int j=1;j<=3;j++)
			{
				int first=1,second=1;
				while(first<=3)
				{
					res.c[i][j]+=c[i][first]*a.c[second][j];
					first++;second++;
				}
			}
		return res;
	}
	void Print()
	{
		for(int i=1;i<=3;i++)
		{
			for(int j=1;j<=3;j++) printf("%lld ",c[i][j]);
			printf("\n");
		}
		printf("\n");
	}
};

int main()
{
	freopen("1027.in","r",stdin);
	freopen("1027.out","w",stdout);
	int t; scanf("%d",&t);
	while(t--)
	{
		Matrix a,b;
		a.Read(); b.Read();
		(a*b).Print();
	}
	return 0;
}


1028 任意阶矩阵的乘法

跟上一题差不多,注意细节

#include<cstdio>
#include<cstring>

struct Matrix{
	long long c[4][4];
	void clear() { memset(c,0,sizeof(c)); }
};

void Read(Matrix &a,int n,int m)
{
	a.clear();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%lld",&a.c[i][j]);
}
void Print(Matrix &a,int n,int m)
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++) printf("%lld ",a.c[i][j]);
		printf("\n");
	}
	printf("\n");
}

Matrix solve(Matrix &a,Matrix &b,int n,int m,int t)
{
	Matrix res; res.clear();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=t;j++)
		{
			int first=1,second=1;
			while(first<=m)
			{
				res.c[i][j]+=a.c[i][first]*b.c[second][j];
				first++;second++;
			}
		}
	return res;
}
int main()
{
	freopen("1028.in","r",stdin);
	freopen("1028.out","w",stdout);
	int t; scanf("%d",&t);
	while(t--)
	{
		int a,b,c; scanf("%d%d%d",&a,&b,&c);
		Matrix x,y;
		Read(x,a,b); Read(y,b,c);
		x=solve(x,y,a,b,c);
		Print(x,a,c);
	}
	return 0;
}


1227 Hotel

很好的一道线段树题目,跟小白逛公园思路差不多,以前做的 http://blog.csdn.net/jiangzh7/article/details/8744258

#include<cstdio>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
const int N=50000+10;
const int inf=0x3f3f3f3f;
int n,m;
int val[N*4];
int z[N*4],y[N*4],s[N*4];

inline void downloading(int p,int l,int r,int m)
{
	if(val[p]!=-1)
	{
		if(val[p]==1)
		{
			z[p<<1]=y[p<<1]=s[p<<1]=0;
			z[(p<<1)+1]=y[(p<<1)+1]=s[(p<<1)+1]=0;
		}
		if(val[p]==0)
		{
			z[p<<1]=y[p<<1]=s[p<<1]=m-l+1;
			z[(p<<1)+1]=y[(p<<1)+1]=s[(p<<1)+1]=r-(m+1)+1;
		}
		val[p<<1]=val[(p<<1)+1]=val[p];
		val[p]=-1;
    freopen("1366.in","r",stdin);
    freopen("1366.out","w",stdout);
	}
}
inline void update(int p)
{
	if(val[p]==-1&&val[p<<1]==val[(p<<1)+1])
	    val[p]=val[p<<1];
}

void change(int p,int l,int r,int a,int b,int c)
{
	if(a<=l&&b>=r)
	{
		val[p]=c;
		z[p]=y[p]=s[p]=(1-c)*(r-l+1);//简写了,仔细看就明白了
		return;
	}
	int m=(l+r)>>1;
	downloading(p,l,r,m);
	if(a<=m) change(p<<1,l,m,a,b,c);
	if(b>m) change((p<<1)+1,m+1,r,a,b,c);
	//z[p]
	if(val[p<<1]==0) z[p]=z[p<<1]+z[(p<<1)+1];
	else z[p]=z[p<<1];
	//y[p]
	if(val[(p<<1)+1]==0) y[p]=y[(p<<1)+1]+y[p<<1];
	else y[p]=y[(p<<1)+1];
	//s[p]
	s[p]=max(y[p<<1]+z[(p<<1)+1],max(s[p<<1],s[(p<<1)+1]));
	update(p);
}

int getres(int d)//写成非递归了
{
	if(s[1]<d) return 0;
	int p=1,l=1,r=n;
	while(l<r)
	{
		int m=(l+r)>>1;
		downloading(p,l,r,m);
		if(s[p<<1]>=d){p<<=1;r=m;continue;}
		if(y[p<<1]+z[(p<<1)+1]>=d) return m-y[p<<1]+1;
		p<<=1;p++;l=m+1;
		update(p);
	}
	return l;
}

void order(int d)
{
	int res=getres(d);
	printf("%d\n",res);
	if(res) change(1,1,n,res,res+d-1,1);
}

int main()
{
    scanf("%d%d",&n,&m);
    change(1,1,n,1,n,0);//让所有人离开,相当于给z[],y[],s[]赋初值
    int temp,x,d;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&temp);
        if(temp==1)//order
        {
            scanf("%d",&d);
            order(d);
        }
        else if(temp==2)//leave
        {
            scanf("%d%d",&x,&d);
            change(1,1,n,x,x+d-1,0);
        }
    }
    return 0;
}
 				    


1256 能被3和11整除吗

数学题。能被3整除的数:所有位上数字之和能被3整除。能被11整除的数:奇数位上数字之和减去偶数位上数字之和能被11整除。

#include<cstdio>
#include<cstring>

char s[300];
int n;
bool three(char *s)
{
	int tmp=0;
	for(int i=0;i<n;i++)
		tmp+=s[i]-'0';
	return tmp%3==0;
}
bool eleven(char *s)
{
	int tmp=0,k=-1;
	for(int i=0;i<n;i++)
		tmp+=(s[i]-'0')*(k=-k);
	return tmp%11==0;
}

int main()
{
	freopen("1256.in","r",stdin);
	freopen("1256.out","w",stdout);
	int t; scanf("%d",&t);
	while(t--)
	{
		memset(s,0,sizeof(s));
		scanf("%s",s); n=strlen(s);
		if(three(s)) printf("yes ");
		else printf("no ");
		if(eleven(s)) printf("yes\n");
		else printf("no\n");
	}
	return 0;
}


1307 windy数

基础数位dp不解释。以前写的  http://blog.csdn.net/jiangzh7/article/details/8820827

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=50;
int a,b;
int L[N],R[N];
int len;
int f[N][2][2][15];

void predoing(int a,int *num)
{
	int le=0;
	while(a)
	{
		num[++le]=a%10;
		a/=10;
	}
	len=max(len,le);
}

int calc(int pos,int d,int u,int last,bool zero)
{
	if(pos==0) return 1;
	int &res=f[pos][d][u][last];
	if(res!=-1) return res;
	int st=d?0:L[pos];
	int ed=u?9:R[pos];
	res=0;
	for(int i=st;i<=ed;i++)
	{
		if(abs(i-last)>=2||zero)
		{
			res+=calc(pos-1,d||i>L[pos],u||i<R[pos],i,i==0&&zero);
		}
	}
	return res;
}

int main()
{
	memset(f,-1,sizeof(f));
	scanf("%d%d",&a,&b);
	predoing(a,L);predoing(b,R);
	printf("%d\n",calc(len,0,0,0,1));
	return 0;
} 				    


1317 Popular Cow

以前做过的,再写一次

该死的CDOJ,居然是多组数据!!!!!坑死我了!!!!WA了N+1次。。。。。。

改了后各种memset

#include<cstdio>
#include<cstring>
#include<stack>
using std::stack;
#define min(a,b) ((a)<(b)?(a):(b))
const int N=10000+10;
int n,m;
struct Link{int y;Link *next;}*head[N];
bool hash[N],inst[N];
stack<int> st;
int belong[N],number,peo[N];
int low[N],now[N],dfstime;
int out[N];

void inLink(int x,int y)
{
	Link *p=new Link;
	p->y=y; p->next=head[x];
	head[x]=p;
}

void dfs(int x)
{
	low[x]=now[x]=++dfstime;
	st.push(x); inst[x]=1; hash[x]=1;
	for(Link *p=head[x];p;p=p->next)
	{
		if(!hash[p->y])
		{
			dfs(p->y);
			low[x]=min(low[x],low[p->y]);
		}
		else if(inst[p->y]) low[x]=min(low[x],now[p->y]);
	}
	if(low[x]==now[x])
	{
		while(!st.empty())
		{
			int u=st.top();st.pop();
			belong[u]=number; inst[u]=0;
			peo[number]++;
			if(u==x) break;
		}
		number++;
	}
}

void tarjan()
{
	for(int i=1;i<=n;i++)
		if(!hash[i]) dfs(i);
	if(!st.empty())
	{
		while(!st.empty())
		{
			int u=st.top();st.pop();
			belong[u]=number; inst[u]=0;
			peo[number]++;
		}
		number++;
	}
}

int solve()
{
	tarjan();
	for(int i=1;i<=n;i++)
	{
		for(Link *p=head[i];p;p=p->next)
		{
			if(belong[i]==belong[p->y]) continue;
			out[belong[i]]++;
		}
	}
	int k=-1;
	for(int i=0;i<number;i++) if(out[i]==0)
	{
		if(k!=-1) return 0;
		if(k==-1) k=i;
	}
	if(k==-1) return 0;
	return peo[k];
}

int main()
{
	freopen("1317.in","r",stdin);
	freopen("1317.out","w",stdout);
	while(scanf("%d%d",&n,&m)==2)
	{
		memset(head,0,sizeof(head));
		memset(belong,0,sizeof(belong));
		memset(peo,0,sizeof(peo));
		memset(out,0,sizeof(out));
		memset(hash,0,sizeof(hash));
		memset(inst,0,sizeof(inst));
		memset(peo,0,sizeof(peo));
		number=dfstime=0;
		memset(low,0,sizeof(low));
		memset(now,0,sizeof(now));
		for(int i=1;i<=m;i++)
		{
			int x,y; scanf("%d%d",&x,&y);
			inLink(x,y);
		}
		printf("%d\n",solve());
	}
	return 0;
}


1322 War

http://blog.csdn.net/jiangzh7/article/details/8949213

第一次写这种删边最短路,基本思路就是倒着做,变成加边,详见上面题解

#include<cstdio>
#include<cstring>
#define min(a,b) ((a)<(b)?(a):(b))
const int N=200+10;
const int Q=10000+10;
const int inf=0x3f3f3f3f;

int n,m,q,g[N][N];
int destroyed[N];
int x[Q],y[Q],op[Q];
int ans[Q],Cnt;

void read()
{
	scanf("%d%d",&n,&m);
	memset(g,0x3f,sizeof(g));
	for(int i=1;i<=n;i++) g[i][i]=0;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		if(z<g[x][y]) g[x][y]=g[y][x]=z;
	}
	scanf("%d",&q);
	for(int i=1;i<=q;i++)
	{
		scanf("%d%d",&op[i],&x[i]);
		if(op[i]==0)
			scanf("%d",&y[i]);
		if(op[i]==1) destroyed[x[i]]=1;
	}
}

void floyd(int k)
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(g[i][j]>g[i][k]+g[k][j])
				g[i][j]=g[i][k]+g[k][j];
}

void work()
{
	for(int i=1;i<=n;i++)
		if(!destroyed[i]) floyd(i);
	for(int i=q;i>0;i--)
	{
		if(op[i]==1)
		{
			destroyed[x[i]]=0;
			floyd(x[i]);
		}
		else{
			if(destroyed[x[i]]||destroyed[y[i]]) 
				ans[Cnt++]=-1;
			else if(g[x[i]][y[i]]==inf)
				ans[Cnt++]=-1;
			else ans[Cnt++]=g[x[i]][y[i]];
		}
	}
	for(int i=Cnt-1;i>=0;i--)
		printf("%d\n",ans[i]);
}

int main()
{
	freopen("1322.in","r",stdin);
	freopen("1322.out","w",stdout);
	int t; scanf("%d",&t);
	while(t--)
	{
		memset(destroyed,0,sizeof(destroyed));
		memset(ans,0,sizeof(ans)); Cnt=0;
		read();
		work();
		printf("\n");
	}
	return 0;
}


1365 木杆上的蚂蚁

经典的蚂蚁爬杆问题 http://blog.csdn.net/jiangzh7/article/details/8950556

#include<cstdio>
#include<cstdlib>
#include<algorithm>
const int N=100+10;
int n,L;
struct node{char name[20];int pos;}a[N];
int time[N];

bool cmp_abs(int a,int b) { return abs(a)<abs(b); }
bool cmp_node(node a,node b) { return a.pos<b.pos; }

void work()
{
	scanf("%d%d",&n,&L);
	for(int i=1;i<=n;i++)
	{
		scanf("%s%d",a[i].name,&a[i].pos);
		char op[10]; scanf("%s",op);
		if(op[0]=='L') time[i]=a[i].pos;
		else time[i]=-(L-a[i].pos);
	}
	std::sort(time+1,time+1+n,cmp_abs);
	std::sort(a+1,a+1+n,cmp_node);
	int head=1,tail=n;
	for(int i=1;i<=n;i++)
	{
		if(time[i]>0)
		{
			printf("%d %s\n",time[i],a[head].name);
			head++;
		}
		else{
			printf("%d %s\n",-time[i],a[tail].name);
			tail--;
		}
	}
}

int main()
{
	freopen("1365.in","r",stdin);
	freopen("1365.out","w",stdout);
	int T; scanf("%d",&T);
	for(int cas=1;cas<=T;cas++)
	{
		printf("Case #%d:\n",cas);
		work();
	}
	return 0;
}


1366 三国杀

有趣的模拟题,细心即可

#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=1000+10;
int n,m;
int add[N],sub[N];

int getint(char *s)
{
	int res=0;
	int len=strlen(s);
	for(int i=0;i<len;i++)
		res=res*10+s[i]-'0';
	return res;
}

void query(int a,int b)
{
	int l=a,r=b;
	if(a>b) std::swap(a,b);
	int dis=std::min(b-a,a+n-b);
	a=l;b=r;
	dis+=add[b]-sub[a];
	if(dis<=1) printf("Yes!\n");
	else printf("I'm sorry.\n");
}

void work()
{
	scanf("%d%d",&n,&m);
	while(m--)
	{
		char s[100];
		scanf("%s",s);
		if(s[0]=='K')
		{
			int x,y; scanf("%d%d",&x,&y);
			query(x,y);
		}
		else{
			int x=getint(s);
			int num; scanf("%s%d",s,&num);
			if(s[0]=='-') sub[x]=num;
			else add[x]=num;
		}
	}
}

int main()
{
	freopen("1366.in","r",stdin);
	freopen("1366.out","w",stdout);
	int t; scanf("%d",&t);
	for(int cas=1;cas<=t;cas++)
	{
		printf("Case #%d:\n",cas);
		memset(sub,0,sizeof(sub));
		memset(add,0,sizeof(add));
		work();
		printf("\n");
	}
	return 0;
}


1373 Boring 11.11

应该算是模拟题吧,只是细节有点多

这一题由于是求最小,所以基本的贪心应该是把最右边一个能够往左移动的1往左移一位即可,这样肯定是会WA的

比如(110)2,我们向左移动显然只能移动第一个1,就成了(1010)2,但是很明显有最优的(1001)2,所以除了往左移,我们也同样需要往右移

具体看看代码

#include<cstdio>

long long n;

void work()
{
	scanf("%lld",&n);
	long long j=1;
	int cnt=0;
	while(j<=n)
	{
		if((j&n)!=0)//当前位为1
		{
			cnt++;//记录需要向右移动的1的个数
			if(((j<<1LL)&n)==0)//前一位为0
			{
				n=n&(~j);
				n=n|(j<<1LL);
				cnt--;//当前位向左移,不需要向右移
				break;
			}
		}
		j=j<<1LL;
	}
	long long tmp=n;
	int one=cnt;//我们用one表示有几个0需要被给城1,用cnt表示有几个1需要被改成0
	int pos=0;
	while(tmp)
	{
		int t=tmp&1;
		if(t && one)//当前位为1
		{
			n=n&(~(1LL<<pos));//当前位改成0
			one--;
			t=0;
		}
		if(!t && cnt)//当前位为0
		{
			n=n|(1LL<<pos);
			cnt--;
		}
		if(one==0 && cnt==0) break;
		pos++;
		tmp>>=1;
	}
	printf("%lld\n",n);
}

int main()
{
	freopen("1373.in","r",stdin);
	freopen("1373.out","w",stdout);
	int t; scanf("%d",&t);
	for(int cas=1;cas<=t;cas++)
	{
		printf("Case #%d: ",cas);
		work();
	}
	return 0;
}


1427 Challenge Me

找这个贪心法的反例,自己YY了很多,WA哭了。。。。。后来无奈之下看网上有一个人yy 1, 2, M-1, 2*M,过了。。。。。=_=!!!

#include <cstdio>
int main()
{
	int T; scanf("%d", &T);
	for(int cas=1;cas<=T;cas++)
	{
		printf("Case #%d:\n", cas);
		int M; scanf("%d", &M);
		if (M <= 2) 
		{
			printf("NO\n");
			continue;
		}
		printf("YES\n4\n");
		printf("1\n2\n%d\n%d\n", M - 1, 2 * M);
	}
	return 0;
}


1488 Flip Game

以前做过的题目 http://blog.csdn.net/jiangzh7/article/details/8592356

简化了一些,题目告诉n=4,而不是读入

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define copymap(a,b) for(int _i=0;_i<n;_i++)for(int _j=0;_j<n;_j++)a[_i][_j]=b[_i][_j];

const int MAXN=30;
const int dx[]={0,0,1,-1,0};
const int dy[]={1,-1,0,0,0};

int n;
int map[MAXN][MAXN];
int oldmap[MAXN][MAXN];
int firstmap[MAXN][MAXN];
int a[MAXN];
int ans=0x7fffffff;

void read()
{
	n=4;
	char s[30];
	for(int i=0;i<n;i++)
	{
		scanf("%s\n",s);
		for(int j=0;j<n;j++)
		    map[i][j]=((s[j]=='b')?1:0);
	}
	copymap(firstmap,map);
}

void change(int x,int y)
{
	for(int k=0;k<5;k++)
	{
		int nx=x+dx[k];
		int ny=y+dy[k];
		if(nx>=n||nx<0) continue;
		if(ny>=n||ny<0) continue;
		map[nx][ny]=1-map[nx][ny];
	}
}

void turn(int sum,int k)
{
	for(int i=1;i<n;i++)
		for(int j=0;j<n;j++)
		    if(map[i-1][j]!=k)
		    {
				change(i,j);
				sum++;
			}
	bool flag=true;
	for(int j=0;j<n;j++)
	    if(map[n-1][j]!=k) {flag=false;break;}
	if(flag) ans=min(ans,sum);
}

void dfs(int x,int sum)
{
	if(x>=n)//边界
	{
		for(int i=0;i<n;i++)
			if(a[i]) change(0,i);
		copymap(oldmap,map);
		turn(sum,1);
		copymap(map,oldmap);
		turn(sum,0);
		copymap(map,firstmap);
		return;
	}
	a[x]=1;
	dfs(x+1,sum+1);
	a[x]=0;
	dfs(x+1,sum);
}

void work()
{
	dfs(0,0);
	if(ans==0x7fffffff) printf("Impossible");
	else printf("%d\n",ans);
}

int main()
{
	read();
	work();
	return 0;
} 				    


1499 Strategic Game

树形dp,记忆化,很少写这类,有点艰难

#include<cstdio>
#include<cstring>
const int N=1500+10;
const int inf=0x3f3f3f3f;
#define min(a,b) ((a)<(b)?(a):(b))
int n;
int father[N],son[N][30],num[N];
int deg[N],root;
int f[N][2];

void read()
{
	for(int i=1;i<=n;i++)
	{
		int x,a;
		scanf("%d:(%d)",&x,&a);
		num[x]=a;
		for(int j=1;j<=num[x];j++)
		{
			int y; scanf("%d",&y);
			father[y]=x;
			son[x][j]=y;deg[y]++;
		}
	}
}

int dfs(int x,int sta)
{
	if(f[x][sta]!=-1) return f[x][sta];
	if(num[x]==0) return f[x][sta]=sta;
	f[x][sta]=sta;
	for(int i=1;i<=num[x];i++)
	{
		if(sta) f[x][sta]+=min(dfs(son[x][i],0),dfs(son[x][i],1));
		else f[x][sta]+=dfs(son[x][i],1);
	}
	return f[x][sta];
}

void work()
{
	root=-1;
	for(int i=0;i<n;i++) 
		if(!deg[i]) {root=i;break;}
	printf("%d\n",min(dfs(root,0),dfs(root,1)));
}

int main()
{
	freopen("1499.in","r",stdin);
	freopen("1499.out","w",stdout);
	while(scanf("%d",&n)==1)
	{
		memset(father,0,sizeof(father));
		memset(son,0,sizeof(son));
		memset(num,0,sizeof(num));
		memset(deg,0,sizeof(deg));
		memset(f,-1,sizeof(f));
		read();
		work();
	}
	return 0;
}


1511 糖果

SCOI2011的第一题,差分约束入门题   http://blog.csdn.net/jiangzh7/article/details/8872699

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=100000+10;
typedef long long LL;
 
int n,m;
struct link{int y,z;link *next;}*head[N];
queue<int> q;
int dist[N],inQ[N];
int relax[N];
 
void inlink(int x,int y,int z)//x-y <= z
{
    link *node=new link;
    node->y=y;node->z=z;
    node->next=head[x];
    head[x]=node;
}
 
bool read()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int op,x,y;
        scanf("%d%d%d",&op,&x,&y);
        if(op==1) // x = y
        {
            inlink(x,y,0);// x-y <= -0
            inlink(y,x,0);// y-x <= -0
        }
        else if(op==2) // x < y
        {
            if(x==y) return 0;
            inlink(x,y,1);// x-y <= -1
        }
        else if(op==3) // x >= y
            inlink(y,x,0);// y-x <= -0
        else if(op==4) // x > y
        {
            if(x==y) return 0;
            inlink(y,x,1);// y-x <= -1
        }
        else if(op==5) // x <= y
            inlink(x,y,0);// x-y <= -0
    }
    return 1;
}
 
bool spfa()
{
    memset(relax,0,sizeof(relax));
    memset(inQ,0,sizeof(inQ));
    while(!q.empty())
    {
        int x=q.front();
        q.pop(); inQ[x]=0;
        for(link *node=head[x];node;node=node->next)
            if(dist[node->y]<dist[x]+node->z)
            {
                dist[node->y]=dist[x]+node->z;
                if(++relax[node->y]>=n) return 0;//circle
                if(!inQ[node->y])
                {
                    inQ[node->y]=1;
                    q.push(node->y);
                }
            }
    }
    return 1;
}
 
LL solve()
{
    for(int i=1;i<=n;i++) 
    {//push all the points in the queue
        dist[i]=1;//every one should have at least one candy
        q.push(i); inQ[i]=1;
    }
    if(!spfa()) return -1;
    LL res=0;
    for(int i=1;i<=n;i++) res+=dist[i];
    return res;
}
 
int main()
{
    if(!read()) printf("-1\n");
    else printf("%lld\n",solve());
    return 0;
}


1548 Easy math

最直接的想法是先算出 t = b^c % M , 然后算出 ans = a^t % M ,那么,就错了。。。。。

我们每次取模不是随便乱取的,一定要是同余的才能每步取余

但是这里并不是同余的

因为M为质数,根据费马小定理,我们需要算出 t = b^c % (M-1) , 再算出 ans = a^t % M , 这样才是同余的

#include<cstdio>
typedef long long LL;
const int M=1000000007;
int mul(int x,int y,int mod)
{
	int ans=1;
	while(y)
	{
		if(y&1) ans=((LL)ans*x)%mod;
		x=((LL)x*x)%mod;
		y>>=1;
	}
	return ans;
}

int main()
{
	freopen("1548.in","r",stdin);
	freopen("1548.out","w",stdout);
	int a,b,c;
	while(scanf("%d%d%d",&a,&b,&c)==3)
	{
		int t=mul(b,c,M-1);
		int ans=mul(a,t,M);
		printf("%d\n",ans);
	}
	return 0;
}


1656/1657 滑雪与时间胶囊  http://blog.csdn.net/jiangzh7/article/details/8935578

#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<algorithm>
using std::queue;
typedef long long LL;
const int N=100000+10;
const int M=1000000+10;
int n,m,h[N];
struct EG{int x,y,z;}edge[M*2];
int L;
int vis[N];
struct Link{int y,z;Link *next;}*head[N];
int f[N];

void add_edge(int x,int y,int z)
{
	edge[L++]=(EG){x,y,z};
	Link *p=new Link;
	p->y=y; p->z=z;
	p->next=head[x];
	head[x]=p;
}

int bfs()
{
	queue<int> Q;
	int number=0;
	Q.push(1); vis[1]=1;
	while(!Q.empty())
	{
		int x=Q.front();Q.pop();
		if((++number)==n) return number;
		for(Link *p=head[x];p;p=p->next)
			if(!vis[p->y])
			{
				vis[p->y]=1;
				Q.push(p->y);
			}
	}
	return number;
}

bool cmp(EG a,EG b)
{
	if(h[a.y]==h[b.y]) return a.z<b.z;
	return h[a.y]>h[b.y];
}

int getroot(int x) { return f[x]==x ? x : f[x]=getroot(f[x]); }
inline void merge(int x,int y) { f[getroot(x)]=getroot(y); }

LL solve()
{
	for(int i=1;i<=n;i++) f[i]=i;
	std::sort(edge,edge+L,cmp);
	LL tot=0;
	for(int i=0;i<L;i++)
	{
		int x=edge[i].x;
		int y=edge[i].y;
		if(!vis[x] || !vis[y]) continue;
		if(getroot(x)==getroot(y)) continue;
		merge(x,y);
		tot+=edge[i].z;
	}
	return tot;
}

int main()
{
	freopen("ski.in","r",stdin);
	freopen("ski.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&h[i]);
	while(m--)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		if(h[a]>=h[b]) add_edge(a,b,c);
		if(h[b]>=h[a]) add_edge(b,a,c);
	}
	//printf("%d %lld\n",bfs(),solve());
	printf("%d ",bfs());
	printf("%lld\n",solve());
	return 0;
}


1662/1663 奇怪的游戏

二分+最大流   http://blog.csdn.net/jiangzh7/article/details/8892677

#include<cstdio>
#include<cstring>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
typedef long long LL;
const int N=40+10;
const int NN=50*50;
const int dx[]={0,0,-1,1};
const int dy[]={1,-1,0,0};
const int inf=0x3f3f3f3f;
const LL  infll=0x3f3f3f3f3f3f3f3fLL;

int n,m;
int map[N][N],color[N][N];
struct EG{int y;LL flow;int next;}edge[NN*10];
int head[NN],L;
int v[NN],h[NN];
int S,T;
LL num[2],sum[2],maxp=0;

void read()
{
	scanf("%d%d",&n,&m);
	int cc=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&map[i][j]);
			color[i][j]=!color[i][j-1];
			if(j==1) color[i][j]=(cc=!cc);
			num[color[i][j]]++;
			sum[color[i][j]]+=map[i][j];
			maxp=max(maxp,map[i][j]);
		}
}

inline int get(int x,int y) { return (x-1)*m+y; }

LL sap(int x,LL flow)
{
	if(x==T) return flow;
	LL res=0;
	for(int i=head[x];i!=-1;i=edge[i].next)
		if(edge[i].flow && h[x]==h[edge[i].y]+1)
		{
			LL t=sap(edge[i].y,min(edge[i].flow,flow-res));
			edge[i].flow-=t;
			edge[i^1].flow+=t;
			if((res+=t)>=flow) return res;
			if(h[S]>T) return res;
		}
	if((--v[h[x]])==0) h[S]=T+1;
	++v[++h[x]];
	return res;
}

void inlink(int x,int y,LL z)
{
	edge[L]=(EG){y,z,head[x]};
	head[x]=L++;
	edge[L]=(EG){x,0,head[y]};
	head[y]=L++;
}

bool check(LL final)
{
	memset(edge,0,sizeof(edge));
	memset(head,-1,sizeof(head));L=0;
	memset(v,0,sizeof(v));
	memset(h,0,sizeof(h));
	S=0;T=get(n,m)+1;
	LL total=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			LL tmp=final-map[i][j];
			//if(tmp<0) return 0;
			if(color[i][j]==0) inlink(S,get(i,j),tmp);
			else inlink(get(i,j),T,tmp);
			total+=tmp;
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=0;k<4;k++)
			{
				int x=i+dx[k],y=j+dy[k];
				if(x<1||x>n||y<1||y>m) continue;
				if (color[i][j]==0) inlink(get(i,j),get(x,y),infll);
			}
	v[0]=T+1;
	LL maxflow=0;
	while(h[S]<T+1) maxflow+=sap(S,infll);
	//fprintf(stderr,"%lld  ->  %lld %lld\n",final,maxflow,total);
	return total==(maxflow*2);
}

inline LL getans(LL x)
{
	return ((LL)n*m*x-sum[0]-sum[1])/2;
}

void work()
{
	if((n*m)%2==0)
	{
		LL L=1,R=infll/1000,M;
		int ans=-1;
		while(L<=R)
		{
			M=L+((R-L)>>1);
			if(check(M)) R=M-1,ans=M;
			else L=M+1;
			//fprintf(stderr,"L=%lld,R=%lld,M=%lld\n",L,R,M);
		}
		//fprintf(stderr,"%d  ->  ",ans);
		if(ans==-1) printf("%d\n",ans);
		else printf("%lld\n",getans(ans));
	}
	else{
		bool flag=0;
		LL x=(sum[0]-sum[1]);
		if(x>=maxp && check(x)) flag=1;
		if(flag) printf("%lld\n",getans(x));
		else printf("-1\n");
	}
}

int main()
{
	int T; scanf("%d",&T);
	while(T--)
	{
		memset(map,0,sizeof(map));
		memset(color,0,sizeof(color));
		sum[0]=sum[1]=num[0]=num[1]=maxp=0;
		read();
		work();
		/*fprintf(stderr,"begin\n");
		check(1018665183LL);
		fprintf(stderr,"end\n");
		check(1027154059LL);
		fprintf(stderr,"end\n");*/
	}
	return 0;
} 				    


1827 种蘑菇的魔理沙

线段树,比较简单

#include<cstdio>
#include<algorithm>
const int N=1000000+10;
#define max(a,b) ((a)>(b)?(a):(b))
typedef long long LL;
int n;
LL val[N*4],add[N*4];

void update(int p)
{
	add[p<<1]+=add[p];
	add[(p<<1)+1]+=add[p];
	add[p]=0;
}

void change(int p,int l,int r,int a,int b,int c)
{
	if(a<=l && b>=r)
	{
		add[p]+=c;
		return;
	}
	int m=(l+r)>>1;
	update(p);
	if(a<=m) change(p<<1,l,m,a,b,c);
	if(b>m) change((p<<1)+1,m+1,r,a,b,c);
	val[p]=max(val[p<<1]+add[p<<1],val[(p<<1)+1]+add[(p<<1)+1]);
}

LL query(int p,int l,int r,int a,int b)
{
	if(a<=l && b>=r) return val[p]+add[p];
	int m=(l+r)>>1; LL x1=0,x2=0;
	update(p);
	if(a<=m) x1=query(p<<1,l,m,a,b);
	if(b>m) x2=query((p<<1)+1,m+1,r,a,b);
	val[p]=max(val[p<<1]+add[p<<1],val[(p<<1)+1]+add[(p<<1)+1]);
	return max(x1,x2);
}

int main()
{
	freopen("1827.in","r",stdin);
	freopen("1827.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x; scanf("%d",&x);
		change(1,1,n,i,i,x);
	}
	int q; scanf("%d",&q);
	while(q--)
	{
		int op,x,l,r;
		scanf("%d%d%d",&op,&l,&r);
		if(l>r) std::swap(l,r);
		if(l<1) l=1;
		if(r>n) r=n;
		if(op==0)
		{
			scanf("%d",&x);
			change(1,1,n,l,r,x);
		}
		else{
			printf("%lld\n",query(1,1,n,l,r));
		}
	}
	return 0;
}


1831 论程序的阿卡林化

由于K是固定的,所以应该联想到 Silding Window 那一题,利用双端队列,具体说不清次(我怕我自己昏了),看看程序就懂了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
using namespace std;
const int N=40000+10;
int n,m,K;
struct node{
	char s[10];
	node(){memset(s,0,sizeof(s));}
}tt[N];
deque<node> deQ;
stack<node> st;
bool flag=0;

void pop()
{
	if(!flag)
	{
		node t=deQ.front();
		deQ.pop_front();
		st.push(t);
	}
	else{
		node t=deQ.back();
		deQ.pop_back();
		st.push(t);
	}
}

void push(node a)
{
	if(!flag)
	{
		if(deQ.size()==K)
		{
			node t=deQ.front(); 
			deQ.pop_front();
			st.push(t);
		}
		deQ.push_back(a);
	}
	else{
		if(deQ.size()==K)
		{
			node t=deQ.back();
			deQ.pop_back();
			st.push(t);
		}
		deQ.push_front(a);
	}
}

void work()
{
	for(int i=1;i<=n;i++) scanf("%s",tt[i].s);
	for(int i=n;i>=1;i--) push(tt[i]);
	while(m--)
	{
		char s[50]; memset(s,0,sizeof(s));
		scanf("%s",s); int len=strlen(s);
		if(s[0]=='A')
		{
			node name; int j=0,k=0;
			while(j<len && s[j]!='(') j++;
			j++;
			while(s[j]!=')') name.s[k++]=s[j++];
			push(name);
		}
		else flag=!flag;
	}
	while(!deQ.empty()) pop();
	while(!st.empty())
	{
		node t=st.top();st.pop();
		puts(t.s);
	}
}

int main()
{
	freopen("1831.in","r",stdin);
	freopen("1831.out","w",stdout);
	while(scanf("%d%d%d",&n,&m,&K)==3)
	{
		work();
		printf("\n");
	}
	return 0;
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值