1、某种密码(password.*)
关于某种密码有如下描述:某种密码的原文A是由N个数字组成,而密文B是一个长度为N的01数串,原文和密文的关联在于一个钥匙码KEY。若KEY=∑?〖Ai*Bi〗,则密文就是原文的一组合法密码。
现在有原文和钥匙码,请编一个程序来帮助他统计到底有多少个符合条件的密文。
【输入数据】
第一行两个数N,KEY,意义同题目描述;
第二行N个数表示原文A,意义同题目描述。
【输出数据】
一个数ANS,表示对于原文A和KEY,有多少组可行的密文B。
【输入样例】
3 2
1 1 2
【输出样例】
2
【样例说明】
密文110,1*1+1*1+0*2=2
密文001,0*1+0*1+1*2=2
一共两组可行的密文。
【数据约定】
60%数据满足N<=25
100%数据满足N<=40,-maxlongint<=∑?Ai<=maxlongint
/* 设了long long类型的变量,用“%lld”怎么也读不进去,必须用cin或者qread */ #include<iostream> #include<cstdio> using namespace std; int n; long long a[50],key; long long qread(){ long long i=0; int j=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)j=-1;ch=getchar();} while(ch<=‘9‘&&ch>=‘0‘){i=i*10+ch-‘0‘;ch=getchar();} return i*j; } long long dfs(int pos,long long sum){ if(pos==n+1){ if(sum==key)return 1; return 0; } long long ans=0; ans+=dfs(pos+1,sum+a[pos]); ans+=dfs(pos+1,sum); return ans; } int main(){ //freopen("Cola.txt","r",stdin); freopen("password.in","r",stdin); freopen("password.out","w",stdout); scanf("%d",&n); key=qread(); for(int i=1;i<=n;i++)a[i]=qread(); cout<<dfs(1,0); }
60分 暴力
2、球的序列(formation.*)
N个编号为1-n的球,每个球都有唯一的编号。这些球被排成两种序列,分别为A、B序列,现在需要重新寻找一个球的序列l,对于这个子序列l中任意的两个球,要求j,k(j<k),都要求满足lj在A中位置比lk在A中位置靠前,却lj在B中位置比lk在B中位置靠前,请你计算这个子序列l的最大长度。
输入:
第一行一个整数,表示N。
第二行N个整数,表示A序列。
第三行N个整数,表示B序列。
样例输入
5
1 2 4 3 5
5 2 3 4 1
样例输出
2
样例说明
L可以是{2,3},也可以是{2,4}
数据范围:
40% N<=5000
100% N<=50000
#include<iostream> #include<cstdio> using namespace std; #define maxn 50010 int n,a[maxn],b[maxn],c[maxn],f[maxn],dp[maxn]; int main(){ freopen("Cola.txt","r",stdin); //freopen("formation.in","r",stdin); //freopen("formation.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); c[a[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); f[i]=c[b[i]];dp[i]=1; } int ans=1; for(int i=2;i<=n;i++) for(int j=1;j<i;j++) if(f[i]>f[j]){ dp[i]=max(dp[i],dp[j]+1); ans=max(ans,dp[i]); } cout<<ans; }
60分 最长上升子序列
3、大逃亡(escape.*)
给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上,矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2)。在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下,你最少要走多少步才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d),那么它们的距离为|a-c|+|b-d|。
输入:
第一行给出数字N,X,Y
第二行给出x1,y1,x2,y2
下面将有N行,给出N个敌人所在的坐标
输出:
在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。
Sample input
2 5 6
0 0 4 0
2 1
2 3
Sample output
2 14
/* 先暴力预处理出每个点离最近的敌人的距离(这个预处理真的特别暴力) 二分答案,在check每个答案的时候顺便记录下这种答案下的最短路,以为check的方法是灌水,所以不费事 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define maxn 1010 int N,n,m,x1,x2,ans1,y1,y2,d[maxn][maxn],ans2,now,len; bool flag,vis[maxn][maxn];//check中要用的 struct node{ int x,y,step; }cur,nxt; int e[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; int abs(int x){ if(x<0)return -x; return x; } bool bfs(int limit){ queue<node>q; cur.x=x1;cur.y=y1;cur.step=0; q.push(cur); while(!q.empty()){ cur=q.front();q.pop();vis[cur.x][cur.y]=0; for(int i=0;i<4;i++){ int xx=cur.x+e[i][0],yy=cur.y+e[i][1]; if(xx<n&&xx>=0&&yy<m&&yy>=0&&d[xx][yy]>=limit&&!vis[xx][yy]){ nxt.x=xx;nxt.y=yy;nxt.step=cur.step+1; if(xx==x2&&yy==y2){ len=nxt.step; return 1; } q.push(nxt); vis[xx][yy]=1; } } } return 0; } bool check(int x){ flag=0; memset(vis,0,sizeof(vis)); if(bfs(x)){ ans2=len; return 1; } return 0; } int main(){ //freopen("Cola.txt","r",stdin); freopen("escape.in","r",stdin); freopen("escape.out","w",stdout); memset(d,127/3,sizeof(d)); scanf("%d%d%d",&N,&n,&m); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); int x,y; int l=0x7fffffff,r=0; for(int i=1;i<=N;i++){ scanf("%d%d",&x,&y); d[x][y]=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) d[i][j]=min(d[i][j],abs(i-x)+abs(j-y)); } for(int i=0;i<n;i++)for(int j=0;j<m;j++)r=max(r,d[i][j]),l=min(l,d[i][j]); r=min(r,min(d[x1][y1],d[x2][y2])); while(l<=r){ now=(l+r)>>1; if(check(now))ans1=now,l=now+1; else r=now-1; } printf("%d %d",ans1,ans2); }
55分 暴力