5 最長公共子串
給定兩個字符串a、b,現有k次機會對字符串中的字符進行修改,使修改后兩個字符串的最長公共子串最長。每一次修改,可以選擇a、b字符串中某一個串的任意位置修改成任意字符。
輸入格式
第一行包括一個正整數 k。
第二行和第三行分別輸入字符串a、b。(每個串的長度不超過500)
輸出格式
輸出為一個整數,表示修改后的兩個串的最長公共子串長度。
輸入樣例
5
aaaaa
bbbbb
輸出樣例
5
Accepted
找兩個字符串的最長公共子串,這個子串要求在原字符串中是連續的。而最長公共子序列則並不要求連續。
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int calculate(string a,string b,int k){ //計算字符串開頭開始最長的公共子串
int pos=0; //已訪問位置
int K=0;//差異
while(pos<a.size()&&pos<b.size()&&(a[pos]==b[pos]||K<k)){
if(a[pos]!=b[pos]) K++;
pos++;
}
return pos;
}
int main(){
int k;
int lena,lenb;
int max=0;
int i,j;
int ans=0;
string a,b;
cin >>k;
cin >> a >> b;
lena=(int)a.size();
lenb=(int)b.size();
for(i=0;i<lena;i++){
for(j=0;j<lenb;j++){
max=calculate(a.substr(i),b.substr(j),k); //substr :主要功能是復制子字符串,要求從指定位置開始,並具有指定的長度。
if(ans<max) ans=max;
}
}
cout << ans << endl;
return 0;
}
6 旋轉骰子
瑪莎有n個骰子,每個骰子的6個面上都恰好有一個0到9之間的數字,且同一個骰子6個面上的數字不會重復。
現在瑪莎將利用這n個篩子來制作新數字。她把n個骰子擺成一排,然后從左到右查看骰子的上表面並讀取,即可得到一個新數字。隨后她不斷的旋轉每個骰子的面就可以得到不同的新數字。旋轉骰子需要滿足以下規則: 1、制作的數字不能包含前導零; 2、制作新數字時不需要使用所有的骰子; 3、使用骰子旋轉,無法將數字9轉換為數字6,反之亦然。
給定n個骰子,瑪莎可以用它們構成從1到x的所有整數。瑪莎想知道,對於給定的n個骰子,這個x的最大取值是多少呢?
輸入格式
第一行僅一個整數n,表示骰子的數量(1≤n≤3)。
接下來n行,每行包含6個整數a[i][j](0≤a[i][j]≤9),表示第i個骰子的第j個面上的數字。
輸出格式
輸出一個整數,即最大數x,瑪莎可以使用她的骰子構成數字從1到x。如果無法構成1,則輸出0。
輸入樣例
3
0 1 3 5 6 8
1 2 4 5 7 8
2 3 4 6 7 9
輸出樣例
98
Accepted
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int main(){
int n;
int i,j,k,t;
int a[500][500];
cin >> n;
for(i=1;i<=n;i++){
for(j=1;j<=6;j++)
cin >> a[i][j];
}
//n==1
if(n==1){
for(j=1,k=1;j<=6;j++){
if(a[1][j]==k) k++;
}
k--;
cout << k << endl;
return 0;
}
//n==2
if(n==2){
for(j=1,k=1;j<=6;j++){
for(t=1;t<=6;t++)
if(a[1][t]==k||a[2][t]==k) k++;
}
k--;
if(k<9){cout << k << endl;return 0;}
else{
for(k=10,j=1;j<=35;j++){
for(i=1;i<=6;i++){
for(t=1;t<=6;t++)
if(a[1][i]*10+a[2][t]==k||a[1][i]+a[2][t]*10==k) k++;
}
}
k--;
cout << k << endl;return 0;
}
}
if(n==3){
for(j=1,k=1;j<=6;j++){
for(t=1;t<=6;t++)
if(a[1][t]==k||a[2][t]==k||a[3][t]==k) k++;
}
k--;
if(k<9){cout << k << endl;return 0;}
else{
for(k=10,j=1;j<=35;j++){
for(i=1;i<=6;i++){
for(t=1;t<=6;t++) if(a[1][i]*10+a[2][t]==k||a[1][t]+a[2][i]*10==k||a[1][i]*10+a[3][t]==k||a[1][t]+a[3][i]*10==k||a[2][i]*10+a[3][t]==k||a[2][t]+a[3][i]*10==k) k++;
}
}
k--;
cout << k << endl;return 0;
}
}
return 0;
}
7 均等筆
n個人圍成一圈,每人有ai支筆。每人可以向左右相鄰的人傳遞筆,每人每次傳遞一支筆消耗的能量為1。求使所有人獲得均等數量的筆的最小能量。
輸入格式
第一行一個整數n ,表示人的個數(30%的數據,n<=1000;100%的數據,n<=1e6)。
接下來n行,每行一個整數 ai。
輸出格式
輸出一個整數,表示使所有人獲得均等筆的最小能量。(答案保證可以用64位有符號整數存儲)
輸入樣例
4
1
2
5
4
輸出樣例
4
Accepted
參考來源:糖果傳遞
對於每個人,假設他的筆數要經過兩類變化:1、從后一個人拿。2、給前一個人,最終的變化結果是變為aver.
- a[1]-X1+X2=aver X2=X1-(a[1]-aver)
- a[2]-X2+X3=aver X3=X1-(a[2]+a[1]-2*aver)
設c[1]=a[1]-aver c[2]=c[1]+a[2]-aver
則有c[i]=c[i-1]+a[i]-aver
則有問題|X1|+|X2|+……+|Xn|的和最小每個都可以用X1表示為|X1|+|X1-c[1]|+|X1-c[2]|+……+|X1-c[n-1]|
絕對值的含義又可以表示數軸上Xi到Ci的距離,所以問題變成了:給定數軸上的n個點,找出一個到他們的距離之和盡量小的點,而這個點就是這些數中的中位數,
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int a[1000005]={0},x[1000005]={0};
int main(){
int n;
long long sum=0,num=0;
int i=0,j;
int aver;
cin >> n;
for(i=0;i<n;i++){
cin >> a[i];
sum+=a[i];
}
aver=(int)(sum/n);
for(i=0;i<n;i++){
x[i]=x[i-1]-a[i-1]+aver;
}
sort(x,x+n);
j=n/2;
for(i=0;i<n;i++){
num+=abs(x[j]-x[i]);
}
cout << num << endl;
return 0;
}
附:數學證明
在數軸上有n個點,找出一個點x,使得她到各個點的距離和最小。求證:該點表示的數就是這n個數的中位數。如果我們把數軸上的點兩兩配對,最大的配最小的,次大的配次小的……則到每組點最近的距離的點在這兩個點中間,那么
如果有奇數個點,那么顯然中間那個點便為所求。
∴該點表示的數是這n個數的中位數得證。