비정필판 - 51nod 기초 훈련(지속 업데이트)
98901 단어 동메달
최대 공통 하위 시퀀스 LCS
이 문제는 매우 보고 싶은 2차원 dp문제로 앞줄을 선택하지 않고 앞줄을 선택하지 않는 상황에서(dp[i+1][j+1]=dp[i][j]+1) 두 문자열의 문자가 같으면 원래의 서열을 바탕으로 한 문자를 추가할 수 있다.만약 두 문자열의 문자가 같지 않다면, 지금까지의 가장 큰 서열의 길이가 얼마인지 찾아서 값을 부여하십시오.dp[i][j]: 첫 번째 문자열(0,i-1)을 나타내고 두 번째 문자열(0,j-1)을 나타내며 가장 긴 공통 서열은 얼마나 깁니까?마지막으로 길이를 기록하는 동시에 이 서열의 길이가 어떻게 더해졌는지 기록한다. 기록이 끝난 후에 종점에서 기점으로 거슬러 올라가 문자열로 거슬러 올라가서 찾은 서열의 문자를 저장하고 뒤집기(종점에서 기점까지)이기 때문에 출력한다.
#include
using namespace std;
const int maxn=1010;
int dp[maxn][maxn];
char opp[maxn][maxn];
int main(){
string s,str;
cin>>s>>str;
dp[0][0]=0;
for(int i=0;i<s.size();i++){
for(int j=0;j<str.size();j++){
if(s[i]==str[j]){
dp[i+1][j+1]=dp[i][j]+1;
opp[i][j]='x';
}else{
if(dp[i][j+1]>dp[i+1][j]){
dp[i+1][j+1]=dp[i][j+1];
opp[i][j]='d';
}else{
dp[i+1][j+1]=dp[i+1][j];
opp[i][j]='r';
}
}
}
}
string ans;
int x=s.size()-1,y=str.size()-1;
while(x>=0&&y>=0){
if(opp[x][y]=='x'){
ans+=s[x];
x--;
y--;
}else if(opp[x][y]=='d'){
x--;
}else{
y--;
}
}
reverse(ans.begin(),ans.end());
cout<<ans<<endl;
//system("pause");
return 0;
}
대수 덧셈(음수 고려)
이것은 좀 영리하다. 모의 가감법 세로식으로 낙서했다.반나절 동안 조정하여 앞의 제로를 고려하지 않았는데, 고려한 후에 또 결과가 제로인 상황이 있다는 것을 잊어버렸다.그리고 분류해서 토론하면 돼요. 저는 정말 귀찮아서 모의고사를 연습한 걸로 할게요.
#include
using namespace std;
string add(string a,string b){
int fa=1,fb=1;
int lena=a.size(),lenb=b.size();
if(a[0]<'0'||a[0]>'9') fa=-1,a=a.substr(1,lena-1),lena--;
if(b[0]<'0'||b[0]>'9') fb=-1,b=b.substr(1,lenb-1),lenb--;
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
string ans;
int shi=0;
int tem=0;
int aa=0,bb=0;
ans="";
if((fa>0 && fb<0) || (fa<0 && fb>0)){
//a-b
if(lena>lenb || (lena==lenb && a[lena-1]>b[lenb-1])){
for(int i=0;i<lenb;i++){
aa=a[i]-'0';
bb=b[i]-'0';
tem=aa-bb+shi;
if(tem<0){
tem=tem+10;
shi=-1;
}else{
shi=0;
}
ans+=(tem+'0');
}
for(int i=lenb;i<lena;i++){
aa=a[i]-'0';
tem=aa+shi;
if(tem<0){
tem=tem+10;
shi=-1;
}else{
shi=0;
}
ans+=(tem+'0');
}
}else{
for(int i=0;i<lena;i++){
aa=a[i]-'0';
bb=b[i]-'0';
tem=bb-aa+shi;
if(tem<0){
tem=tem+10;
shi=-1;
}else{
shi=0;
}
ans+=(tem+'0');
}
for(int i=lena;i<lenb;i++){
bb=b[i]-'0';
tem=bb+shi;
if(tem<0){
tem=tem+10;
shi=-1;
}else{
shi=0;
}
ans+=(tem+'0');
}
ans+='-';
}
//b-a
if(fa<0 && fb>0){
int len=ans.size();
if(ans[len-1]=='-') ans=ans.substr(0,len-1);
else ans+='-';
}
}else{
//(a+b) or -(a+b)
if(lena>lenb){
for(int i=0;i<lenb;i++){
aa=a[i]-'0';
bb=b[i]-'0';
tem=aa+bb+shi;
shi=tem/10;
tem=tem%10;
ans+=(tem+'0');
}
for(int i=lenb;i<lena;i++){
aa=a[i]-'0';
tem=aa+shi;
shi=tem/10;
tem=tem%10;
ans+=(tem+'0');
}
}else{
for(int i=0;i<lena;i++){
aa=a[i]-'0';
bb=b[i]-'0';
tem=aa+bb+shi;
shi=tem/10;
tem=tem%10;
ans+=(tem+'0');
}
for(int i=lena;i<lenb;i++){
bb=b[i]-'0';
tem=bb+shi;
shi=tem/10;
tem=tem%10;
ans+=(tem+'0');
}
}
if(shi) ans+=(shi+'0');
if(fa<0) ans+='-';
}
int cnt=0;
int f=0;
int len=ans.size();
for(int i=len-1;i>=0;i--){
if(ans[i]=='-'){
f=1;
continue;
}
if(ans[i]=='0') cnt++;
else break;
}
if(f) cnt++;
ans=ans.substr(0,len-cnt);
if(ans==""){
return "0";
}
if(f) ans+='-';
reverse(ans.begin(),ans.end());
return ans;
}
int main(){
string a,b;
cin>>a>>b;
string ans;
ans=add(a,b);
cout<<ans<<endl;
//system("pause");
return 0;
}
day2
역순
#include
using namespace std;
const int maxn=50010;
typedef long long ll;
ll a[maxn],b[maxn];
ll cnt;
void merge_sort(int l,int r){
if(r-l>0){
int mid=(l+r)/2;
int i=l;
int p=l,q=mid+1;
merge_sort(l,mid);
merge_sort(mid+1,r);
while(p<=mid || q<=r){
if(q>r||(p<=mid&&a[p]<=a[q])){
b[i++]=a[p++];
}else{
b[i++]=a[q++];
cnt=cnt+mid-p+1;
}
}
for(i=l;i<=r;i++){
a[i]=b[i];
}
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
merge_sort(1,n);
cout<<cnt<<endl;
//system("pause");
return 0;
}
#include
using namespace std;
const int maxn=50010;
typedef long long ll;
ll a[maxn],b[maxn];
ll ans;
ll t[maxn];
int n;
int lowbit(int x){
return x&-x;
}
void add(int x){
while(x<=n){
t[x]++;
x+=lowbit(x);
}
}
ll sum(int x){
ll res=0;
while(x>=1){
res+=t[x];
x-=lowbit(x);
}
return res;
}
bool cmp(int x,int y){
if(a[x]==a[y]) return x>y;
return a[x]>a[y];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=i;
}
sort(b+1,b+1+n,cmp);
for(int i=1;i<=n;i++){
add(b[i]);
ans+=sum(b[i]-1);
}
cout<<ans<<endl;
return 0;
}
대수 곱셈
여전히 시뮬레이션을 해서 쓸 때 약간의 착오가 생겼다.
terminate called after throwing an instance of ‘std::out_of_range’ what(): basic_string::substr 솔루션:substr 방법의 전후 코드를 찾아서 가능한 경계 조건을 배제합니다.
다른 건 잘 됐어.
#include
using namespace std;
const int maxn=50010;
typedef long long ll;
string add(string a,string b){
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
string ans;
int shi=0;
int tem=0;
int aa=0,bb=0;
int lena=a.size(),lenb=b.size();
ans="";
for(int i=0;i<lena;i++){
aa=a[i]-'0';
bb=b[i]-'0';
tem=aa+bb+shi;
shi=tem/10;
tem=tem%10;
ans+=(tem+'0');
}
for(int i=lena;i<lenb;i++){
bb=b[i]-'0';
tem=bb+shi;
shi=tem/10;
tem=tem%10;
ans+=(tem+'0');
}
if(shi) ans+=(shi+'0');
int cnt=0;
int len=ans.size();
for(int i=len-1;i>=0;i--){
if(ans[i]=='0') cnt++;
else break;
}
ans=ans.substr(0,len-cnt);
if(ans==""){
return "0";
}
reverse(ans.begin(),ans.end());
return ans;
}
string mul(string a,string b){
int fa=1,fb=1;
int lena=a.size(),lenb=b.size();
if(a[0]=='-'){
fa=-1;a.substr(1,lena-1);lena--;}
if(b[0]=='-'){
fb=-1;b.substr(1,lenb-1);lenb--;}
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
if(lenb>lena){
string temp=a;
a=b;
b=temp;
int tt=lena;
lena=lenb;
lenb=tt;
}
vector<string> ve;
int num=0;
for(int i=0;i<lenb;i++){
string ans;
int p=b[i]-'0';
int shi=0;
for(int j=0;j<lena;j++){
num=(a[j]-'0')*p+shi;
shi=num/10;
num%=10;
ans+=(num+'0');
}
string sh;
sh="";
sh=(shi+'0');
ans+=sh;
reverse(ans.begin(),ans.end());
for(int j=0;j<i;j++){
ans+="0";
}
ve.push_back(ans);
shi=0;
num=0;
}
string s,str;
s=ve[0];
for(int i=1;i<ve.size();i++){
s=add(s,ve[i]);
}
int cnt=0;
int len=s.size();
for(int i=0;i<len;i++){
if(s[i]=='0') cnt++;
else break;
}
s=s.substr(cnt,len-cnt);
if(s==""){
return "0";
}
if(fa<0 && fb<0){
;
}else if(fa>0 && fb>0){
;
}else{
str="-";
}
str+=s;
return str;
}
int main(){
string a,b;
cin>>a>>b;
cout<<mul(a,b)<<endl;
//system("pause");
return 0;
}
day3
N의 계승
아이디어는 A [i] A [i] A [i] A [i] 수조로 저장하고 각 수조에 14자리수를 저장하며 연산을 롱롱롱의 범위에서 제어할 수 있다. 첫 번째 순환은 어느 수를 곱해야 하는지(1~n 중), 두 번째 순환은 몇 개의 A [i] A [i] A [i] A [i]를 사용했고 l l개를 사용했다.ccc는 저장할 수 없는 진위수를 저장한다. 만약 있다면 다음 A[i] A[i] A[i]에 저장하고 ll l로 업데이트한 다음에 순환 출력 결과를 통해 그룹을 연결하여 보여준다.
printf("%0.14lld",...);
//
#include
using namespace std;
typedef long long ll;
#define mod 100000000000000
ll A[10000000];
int main(){
ll n;
scanf("%lld",&n);
A[0]=1;
ll i,j,l=0;
for(i=1;i<=n;i++){
ll c=0;
for(j=0;j<=l;j++){
ll t=A[j]*i+c;
A[j]=t%mod;
c=t/mod;
}
if(c!=0){
A[++l]=c;
}
}
printf("%lld",A[l]);
for(int i=l-1;i>=0;i--){
printf("%0.14lld
",A[i]);
}
//system("pause");
return 0;
}
N의 곱하기 길이
대수의 성질에 따라: log10(x)log10(x)log10(x), xxx가 10이면 결과는 1, 1위;100위, 결과는 2, 3위... 우리는 총괄할 수 있다, n!n! n!몇 분이면 l o g 10 (n!)log10(n!) log10(n!)의 결과 더하기 1.데이터 범위는 106 10^6 106으로 우리는 선형의 누적법으로 결과를 낼 수 있다.마지막으로 정돈할 때 플로어 함수를 사용했지만 소수점 자릿수가 많을 때 오류가 발생했습니다.강제로 정돈하여 최종적으로 정확한 답안을 얻었다.
#include
using namespace std;
int main(){
double ans=0;
int n;
cin>>n;
for(int i=1;i<=n;i++){
ans+=log10(i*1.0);
}
cout<<ans<<endl;
cout<<(long long)(ans)+1<<endl;
//system("pause");
return 0;
}
바둑 이론(세 가지 간단한 바둑 모델)
Bash 게임
A, B 두 사람이 한 무더기의 돌을 가지고 모두 n개를 가지는데 매번 [1,k]개를 가지면 누가 먼저 들고 누가 이긴다.번갈아 잡다
만약 n이 k+1의 배수라면 A가 임의의 값 x를 취하든 B는 k+1-x를 취하면 필승을 보장할 수 있다.같은 이치로 n이 k+1의 배수가 아니라면 첫 번째 단계에서 n%(k+1)를 얻은 다음에 AB가 신분을 바꾸는 것과 같으니 A가 반드시 이길 것이다.
#include
using namespace std;
typedef long long ll;
ll n,k;
int t;
int main(){
cin>>t;
while(t--){
cin>>n>>k;
if(n%(k+1)) cout<<"A"<<endl;
else cout<<"B"<<endl;
}
return 0;
}
Nim 게임
A, B 두 사람은 n더미의 돌을 들고, 한 무더기의 돌을 [1,∞][1,\infty][1,∞]개씩 들고, 매번 최소한 하나를 들고, 최대 한 무더기를 들고, 가장 먼저 다 잡은 사람이 이긴다.A선수.
#include
using namespace std;
typedef long long ll;
int n;
ll a;
ll ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a;
ans^=a;
}
if(ans) cout<<"A"<<endl;
else cout<<"B"<<endl;
//system("pause");
return 0;
}