【网易】2018校招内推编程题集合
一丶彩色的方块
小易有一些彩色的砖块。每种颜色由一个大写字母表示。各个颜色砖块看起来都完全一样。现在有一个给定的字符串s,s中每个字符代表小易的某个砖块的颜色。小易想把他所有的砖块排成一行。如果最多存在一对不同颜色的相邻砖块,那么这行砖块就很漂亮的。请你帮助小易计算有多少种方式将他所有砖块排成漂亮的一行。(如果两种方式所对应的砖块颜色序列是相同的,那么认为这两种方式是一样的。)
例如: s = "ABAB",那么小易有六种排列的结果:
"AABB","ABAB","ABBA","BAAB","BABA","BBAA"
其中只有"AABB"和"BBAA"满足最多只有一对不同颜色的相邻砖块。
思路: 最多有一对
显然最多只能存在两种字符或者只有一种字符也可以
1 #include <cstdio> 2 #include <cctype> 3 #include <cstring> 4 5 int n,cnt; 6 7 int sum[30]; 8 9 char s[100]; 10 11 int hh() { 12 scanf("%s",s+1); 13 n=strlen(s+1); 14 for(int i=1;i<=n;++i) ++sum[s[i]-'A'+1]; 15 for(int i=1;i<=26;++i) if(sum[i]) ++cnt; 16 if(cnt>2) printf("0\n"); 17 else if(cnt==1) printf("1\n"); 18 else printf("2\n"); 19 return 0; 20 } 21 22 int sb=hh(); 23 int main(int rgc,char**argv) {;}
二丶等差数列
如果一个数列S满足对于所有的合法的i,都有S[i + 1] = S[i] + d, 这里的d也可以是负数和零,我们就称数列S为等差数列。
小易现在有一个长度为n的数列x,小易想把x变为一个等差数列。小易允许在数列上做交换任意两个位置的数值的操作,并且交换操作允许交换多次。但是有些数列通过交换还是不能变成等差数列,小易需要判别一个数列是否能通过交换操作变成等差数列
思路:排序之后一个for循环判断
每一个数减它前一个数的差是否相等
1 #include <cstdio> 2 #include <cctype> 3 #include <algorithm> 4 5 const int MAXN=10010; 6 7 int n; 8 9 int a[MAXN]; 10 11 inline void read(int&x) { 12 int f=1;register char c=getchar(); 13 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 14 for(;isdigit(c);x=x*10+c-48,c=getchar()); 15 x=x*f; 16 } 17 18 int hh() { 19 read(n); 20 for(int i=1;i<=n;++i) read(a[i]); 21 std::sort(a+1,a+1+n); 22 int d=a[2]-a[1]; 23 bool flag=false; 24 for(int i=3;i<=n;++i) { 25 if(d!=a[i]-a[i-1]) { 26 flag=true; 27 printf("Impossible\n"); 28 break; 29 } 30 } 31 if(!flag) printf("Possible\n"); 32 return 0; 33 } 34 35 int sb=hh(); 36 int main(int argc,char**argv) {;}
三丶交错01串
如果一个01串任意两个相邻位置的字符都是不一样的,我们就叫这个01串为交错01串。例如: "1","10101","0101010"都是交错01串。
小易现在有一个01串s,小易想找出一个最长的连续子串,并且这个子串是一个交错01串。小易需要你帮帮忙求出最长的这样的子串的长度是多少。
思路:每一个字符都可以作为一个子串 长度为1
如果相邻的两个字符不相等 则len[i]=len[i-1]+1;
1 #include <cstdio> 2 #include <cctype> 3 #include <cstring> 4 5 const int MAXN=110; 6 7 int n; 8 9 int len[MAXN]; 10 11 char s[MAXN]; 12 13 int hh() { 14 scanf("%s",s+1); 15 n=strlen(s+1); 16 for(int i=1;i<=n;++i) { 17 len[i]=1; 18 if(s[i]!=s[i-1]) len[i]+=len[i-1]; 19 } 20 int ans=-1; 21 for(int i=1;i<=n;++i) 22 ans=len[i]>ans?len[i]:ans; 23 printf("%d\n",ans); 24 return 0; 25 } 26 27 int sb=hh(); 28 int main(int argc,char**argv) {;}
四丶操作序列
小易有一个长度为n的整数序列,a_1,...,a_n。然后考虑在一个空序列b上进行n次以下操作:
1、将a_i放入b序列的末尾
2、逆置b序列
小易需要你计算输出操作n次之后的b序列。
思路:每次把a[i] 插入到 b 序列上 再把b序列翻转
其实我们可以看出来 每次翻转对序列的影响就是你插入a[i]的位置不同
显然 插入一个a[i]之后翻转 下一个a[i] 相当于插入到 b 序列翻转之前的队首
变量flag 记录当前a[i]是插在队首还是队尾
1 #include <cstdio> 2 #include <cctype> 3 4 const int MAXN=200010; 5 6 int n; 7 8 int a[MAXN],b[MAXN<<1]; 9 10 inline void read(int&x) { 11 int f=1;register char c=getchar(); 12 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 13 for(;isdigit(c);x=x*10+c-48,c=getchar()); 14 x=x*f; 15 } 16 17 int hh() { 18 read(n); 19 int l=200000,r=200000,flag=1; 20 for(int i=1;i<=n;++i) read(a[i]); 21 for(int i=1;i<=n;++i) { 22 if(flag) b[++r]=a[i]; 23 else b[l--]=a[i]; 24 flag^=1; 25 } 26 if(n%2==1) { 27 for(int i=r;i>r-n+1;--i) printf("%d ",b[i]); 28 printf("%d",b[r-n+1]); 29 } 30 else { 31 for(int i=l+1;i<l+n;++i) printf("%d ",b[i]); 32 printf("%d",b[l+n]); 33 } 34 return 0; 35 } 36 37 int sn=hh(); 38 int main(int argc,char**argv) {;}
五丶独立的小易
小易为了向他的父母表现他已经长大独立了,他决定搬出去自己居住一段时间。一个人生活增加了许多花费: 小易每天必须吃一个水果并且需要每天支付x元的房屋租金。当前小易手中已经有f个水果和d元钱,小易也能去商店购买一些水果,商店每个水果售卖p元。小易为了表现他独立生活的能力,希望能独立生活的时间越长越好,小易希望你来帮他计算一下他最多能独立生活多少天。
思路:一个数学题 很水
有个坑要注意一下,d元钱可能全部用来付房租 也就是说f可能大到 d全用来付房租也吃不完 需要特判一下
1 #include <cstdio> 2 #include <cctype> 3 #include <iostream> 4 5 typedef long long LL; 6 7 LL x,f,p,d; 8 9 int hh() { 10 std::cin>>x>>f>>d>>p; 11 d-=f*x; 12 if(d<=0) { 13 d+=f*x; 14 printf("%d\n",d/x); 15 return 0; 16 } 17 int day=d/(x+p); 18 printf("%lld\n",day+f); 19 return 0; 20 } 21 22 int sb=hh(); 23 int main(int argc,char**argv) {;}
PS:前五个题还是很水的
六丶堆棋子
小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.
思路:对于一维的情况 我们知道所有点到一个点移动的次数最少 最优的情况就是移动到这些点的中位数
对于二维同样如此 结论就是这样的点不一定在题目给定的n个点中 而是x和y随机组合的n×n个坐标
证明不懂。。
那么就n*n枚举每一个点 判断n个点到这个坐标的最小曼哈顿距离
1 #include <cstdio> 2 #include <cctype> 3 #include <algorithm> 4 5 typedef long long LL; 6 7 const int MAXN=110; 8 9 int n; 10 11 int x[MAXN],y[MAXN]; 12 13 LL ans[MAXN],v[MAXN]; 14 15 inline LL abs(LL p) {return p<0?-p:p;} 16 17 inline void read(int&x) { 18 int f=1;register char c=getchar(); 19 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 20 for(;isdigit(c);x=x*10+c-48,c=getchar()); 21 x=x*f; 22 } 23 24 int hh() { 25 read(n); 26 for(int i=1;i<=n;++i) read(x[i]); 27 for(int i=1;i<=n;++i) read(y[i]); 28 for(int i=1;i<=n;++i) ans[i]=(1ll<<62); 29 30 for(int i=1;i<=n;++i) 31 for(int j=1;j<=n;++j) { 32 int tot=0; 33 for(int k=1;k<=n;++k) 34 v[++tot]=abs(x[k]-x[i])+abs(y[k]-y[j]); 35 std::sort(v+1,v+1+tot); 36 LL sum=0; 37 for(int k=1;k<=n;++k) sum+=v[k],ans[k]=ans[k]>sum?sum:ans[k]; 38 } 39 40 for(int i=1;i<n;++i) printf("%lld ",ans[i]); 41 printf("%lld\n",ans[n]); 42 43 return 0; 44 } 45 46 int sb=hh(); 47 int main(int argc,char**argv) {;}
七丶疯狂队列
小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。
思路:要让差最大 我们贪心的想一下 肯定是最大的和最小的数在一起产生的贡献最大
sort排序 在一个最大值傍边放一个最小值和一个次小值,两边再放次大值,再放次小值
之后一个数的安放要判断一下 不判断的话程序下方的数据可以卡掉上面的做法
1 #include <deque> 2 #include <cstdio> 3 #include <cctype> 4 #include <algorithm> 5 6 const int MAXN=110; 7 8 int n; 9 10 int a[MAXN]; 11 12 inline void read(int&x) { 13 int f=1;register char c=getchar(); 14 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 15 for(;isdigit(c);x=x*10+c-48,c=getchar()); 16 x=x*f; 17 } 18 19 int hh() { 20 read(n); 21 for(int i=1;i<=n;++i) read(a[i]); 22 23 std::sort(a+1,a+1+n); 24 int l=1,r=n-1; 25 std::deque<int> dq; 26 dq.push_back(a[n]); 27 int flag=0; 28 while(l<=r) { 29 if(!flag) { 30 if(l<=r) dq.push_front(a[l++]); 31 if(l<=r) dq.push_back(a[l++]); 32 flag^=1; 33 } 34 else { 35 if(l<=r) dq.push_front(a[r--]); 36 if(l<=r) dq.push_back(a[r--]); 37 flag^=1; 38 } 39 40 } 41 if(abs(dq[n-1]-dq[n-2])<abs(dq[n-1]-dq[0])){ 42 dq.push_front(dq.back()); 43 dq.pop_back(); 44 } 45 std::deque<int>::iterator it; 46 it=dq.begin(); 47 int p=*it,sum=0; 48 for(++it;it!=dq.end();++it) { 49 sum+=abs(*it-p); 50 p=*it; 51 } 52 printf("%d\n",sum); 53 return 0; 54 } 55 56 int sb=hh(); 57 int main(int argc,char**argv) {;} 58 59 /* 60 15 61 1 1 1 1 1 1 1 500 500 500 500 1000 1000 1000 1000 62 */
八丶小易喜欢的数列
小易非常喜欢拥有以下性质的数列:
1、数列的长度为n
2、数列中的每个数都在1到k之间(包括1和k)
3、对于位置相邻的两个数A和B(A在B前),都满足(A <= B)或(A mod B != 0)(满足其一即可)
例如,当n = 4, k = 7
那么{1,7,7,2},它的长度是4,所有数字也在1到7范围内,并且满足第三条性质,所以小易是喜欢这个数列的
但是小易不喜欢{4,4,4,2}这个数列。小易给出n和k,希望你能帮他求出有多少个是他会喜欢的数列。
思路:动态规划
我们不妨设dp[i][j] 表示前i个数 以j结尾的方案数是多少
我们向结尾填一个数 j
显然 dp[i][j]=dp[i-1][1] + dp[i-1][2]... + dp[i-1][j-1] + dp[i][j] + sum{dp[i-1][k]} (k>j&&k%j!=0)
我们可以用总方案数减去不合法方案数来求得 dp[i][j] (直接统计合法方案数也可以)
1 #include <cstdio> 2 #include <cctype> 3 4 typedef long long LL; 5 const int mod=1e9+7; 6 const int MAXN=100010; 7 8 int n,k; 9 10 int dp[11][MAXN]; 11 12 inline void read(int&x) { 13 int f=1;register char c=getchar(); 14 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 15 for(;isdigit(c);x=x*10+c-48,c=getchar()); 16 x=x*f; 17 } 18 19 int hh() { 20 read(n);read(k); 21 dp[0][1]=1; 22 for(int i=1;i<=n;++i) { 23 LL sum=0; 24 for(int j=1;j<=k;++j) { 25 sum+=dp[i-1][j]; 26 sum%=mod; 27 } 28 for(int j=1;j<=k;++j) { 29 LL _sum=0; 30 for(int l=j+j;l<=k;l+=j) { 31 _sum+=dp[i-1][l]; 32 _sum%=mod; 33 } 34 dp[i][j]=(sum-_sum+mod)%mod; 35 } 36 } 37 LL ans=0; 38 for(int i=1;i<=k;++i) 39 ans=(ans+dp[n][i])%mod; 40 printf("%lld\n",ans); 41 return 0; 42 } 43 44 int sb=hh(); 45 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现