快省选了,在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;
}