紫书(第一、二、三章,程序设计入门)

吃透这本书?吃透这本书。


第一章


库函数:(历史沉淀下来的大智慧)

常用的有pow,sqrt,abs……。这其实挺能引起我们深思的,就是这些函数背后隐藏着什么,靠什么方法实现的?

sqrt():


(1)、开根号我们不知道怎么求,但是我们可以猜答案啊!脑袋里第一个思路就是二分,话不多说,开工。

#define eps 1e-8
double sqrt(double x){
    double L=0,R,M;
    if(x>1)R=x;
    else if(x==1)return 1;
    else if(x>=0)R=1;
    else{puts("ERROR,can't sqrt(nagative)!");return -1;}
    while(R-L>eps){
        M=(L+R)/2;
        if(M*M<x)L=M;
        else R=M;
    }
    return M;
}

然而这个有点太慢了。
(2)、牛顿迭代。 x 0 = x 0 F ( x ) F ( x ) 就是这个东东,主要用来求高阶方程,当然,求平方根也适用。
它的原理就是用切线一直逼近。
网上的图
就像这个图,求 2 ,也就是求 f ( x ) 函数与x轴焦点,就这样一直逼近就好了。在这里求平方根的公式就变成了 x 0 = x 0 x 0 2 a 2 x 0 = x 0 + a x 0 2

#define eps 1e-8
double my_sqrt(double x){
    double last,now=x;
    do{
        last=now;
        now=(now+x/now)/2;
    }while(abs(now-last)>eps);
    return now;
}

但是还是稍微有一点点慢。
(3)、黑科技 神秘数字0x5f3759df
只不过这个快是快,准确度差了一些。system应该用的不是这个吧,,

float my_sqrt(float x){
    float xhalf =0.5f*x;
    int i=*(int*)&x;
    i=0x5f375a86- (i>>1);
    x=*(float*)&i;
    x=x*(1.5f-xhalf*x*x);
    x=x*(1.5f-xhalf*x*x);
    x=x*(1.5f-xhalf*x*x);
    return 1/x;
}

ln():

求ln函数我们可以利用泰勒级数,众所周知

l n ( 1 + x ) = n = 1 ( 1 ) n + 1 n x n = x x 2 2 + x 3 3

但是这个函数收敛太慢了,优化一下。
l n ( x ) = l n ( 1 + y 1 y ) = 2 y n = 0 y 2 n 2 n + 1 = 2 y ( 1 1 + y 2 3 + y 4 5 + )
y = x 1 x + 1 ;

众所周知, l n ( 1 + x ) 的泰勒展开在距离1比较远不准确。
经过大量计算引入一个常数 r =1.227.
l n ( 10 a r b x ) = a l n ( 10 ) + b l n ( r ) + l n ( x )
程序:

#define eps 1e-30;
const double ln10=2.3025850929940456840179914547;
const double lnr=0.2002433314278771112016301167;
//用于计算ln(1+y/1-y)
double Ln(double y){
    double ans=1,y2=y*y,t=y2,temp=t/3;
    for(int i=3;temp>eps;temp=(t*=y2)/(i+=2))ans+=temp;
    return 2*y*ans;
}
//优化计算ln(x),因为ln(1+x)泰勒展开在距离x比较远的时候不准。
double ln(double x){
    int k=0,l=0;
    //将x优化到(0.1,1]
    for(;x>1;k++)x/=10;
    for(;x<=0.1;k--)x*=10;
    //将x优化到[0.9047,1.10527199) 
    for(;x<0.9047;l--)x*=1.2217;
    //根据上面公式计算
    return k*ln10+l*lnr+Ln((x-1)/(x+1));
}
double log(double x){
    return ln(x)/ln2;
}
double log10(double x){
    return ln(x)/ln10;
}

pow(double,double)

1.牛顿迭代。

既然上面的 l n ( x ) 函数已经实现那就可以牛顿迭代了啊。

a b = x l n ( x ) b l n ( a ) = 0
F ( x ) = l n ( x ) b l n ( a ) 所以牛顿迭代的迭代公式为:
x 0 = x 0 F ( x 0 ) F ( x 0 ) = x 0 l n ( x 0 ) b l n ( a ) 1 x 0 = x 0 x l n ( x 0 ) + b x 0 l n ( a )
代码:

double pow(double a,double b){
    double last,now=a,lna=ln(a);
    do{
        last=now;
        now=now-now*ln(now)+b*now*lna;
    }while(abs(now-last)>eps);
    return now;
}

但是这个代码速度太慢了,只能处理较小的数。

2.泰勒级数展开

a b = e b l n ( a ) = n = 0 x n n !

double exp(double x){
    double ans=1,temp=x;
    for(int i=1;temp>eps;temp=temp*x/++i)ans+=temp;
    return ans;
}
double pow(double a,double b){
    double x=b*log(a)/log(exp(1));
    return exp(x);
}

s i n ( x ) , c o s ( x ) , t a n ( x ) , a r c s i n ( x ) ,就不一一举例了,无非都是泰勒展开和牛顿迭代而已。


变量输入及输出

c常用输入输出:

scanf("%d",&_int);
scanf("%lf",&_double);
do{
    scanf("%c",&_char);//没有智能判断
}while(_char==' '||_char=='\n');
scanf("%s",_charArry);
printf("%d %f %c %s\n",_int,_double,_char,_charArry);
scanf("%*d");//只读入,不赋值

更加快速的

_char=getchar();
gets(_charArry);
putchar(_char);
puts(_charArry);

更更快速地,自己写的输入输出

/*******************************************************************/
/*******************************************************************/
template<class T>
inline int read(T &x){
    char ch;
    bool flag=false;
    if((ch=getchar())==EOF)return -1;
    for(;!isdigit(ch);ch=getchar())if(ch=='-')flag=true;
    for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=flag?-x:x;
    return 1;
}
template<class T>
inline void write(T x,bool isnewline=false){
    static const int maxlen=100;
    static char s[maxlen];
    if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int len=0;
    for(;x;x/=10)s[len++]=x%10+'0';
    if(isnewline)puts(s);
    else for(int i=len-1;i>=0;i--)putchar(s[i]);
}
/*******************************************************************/
/*******************************************************************/
atoi(char *); 字符串转 int
atof(char *); 字符串转 double
atoll(char *); 字符串转 long long

第二章

循环

for(;;){}
do{}while();
while(){}

n ! 的计算:引申出来一个定理, n ! 的近似计算公式: n ! = 2 n π ( n e ) n


第三章

数组和字符串

int a[maxn],b[maxn];
memcpy(b,a,sizeof(int)*K);//将a中K个数复制到b数组中
memset(a,0,sizeof a);//将a赋值为0

习题P57(本章较水,不做解析)

蛇形填数

#include<bits/stdc++.h>
using namespace std;
const int N=20;
int a[20][20];
int main(){
    int n,x,y,tot;
    scanf("%d",&n);
    memset(a,0,sizeof a);
    tot=a[x=0][y=n-1]=1;
    while(tot<n*n){
        while(x+1<n&&!a[x+1][y])a[++x][y]=++tot;
        while(y-1>=0&&!a[x][y-1])a[x][--y]=++tot;
        while(x-1>=0&&!a[x-1][y])a[--x][y]=++tot;
        while(y+1<n&&!a[x][y+1])a[x][++y]=++tot;
    }
    for(x=0;x<n;x++){
        for(y=0;y<n;y++)printf("%3d",a[x][y]);
        puts("");
    }
    return 0;
}

UVa 272 (Tex Quotes)
https://vjudge.net/problem/UVA-272

//刘汝佳大佬的代码,膜
#include<bits/stdc++.h>
using namespace std;
int main(){
    int c,q=1;
    while(~(c=getchar())){
        if(c=='"')printf("%s",q?"``":"''"),q=!q;
        else printf("%c",c);
    }
    return 0;
}

UVa 1585(Score)
https://vjudge.net/problem/UVA-1585

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N;cin>>N;
    while(N--){
        string s;cin>>s;
        int now=0,ans=0;
        for(int i=0;i<s.length();i++){
            if(s[i]=='O')now++;
            else now=0;
            ans+=now;
        }
        cout<<ans<<endl;
    }
    return 0;
}

UVa 1586(Molar Mass)
https://vjudge.net/problem/UVA-1586

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N;cin>>N;
    map<char,double>mp;
    mp['C']=12.01;mp['H']=1.008;mp['O']=16.00;mp['N']=14.01;
    while(N--){
        string s;cin>>s;
        double ans=0;
        for(int i=0;i<s.length();i++){
            if(mp[s[i]]){
                if(i+1>=s.length()||s[i+1]>'9'){
                    ans+=mp[s[i]];
                }
                else{
                    int kk=0;
                    double kkk=mp[s[i]];
                    while(i+1<s.length()&&!mp[s[i+1]]){
                        kk*=10;
                        kk+=s[i+1]-'0';
                        i++;
                    }
                    ans+=kk*kkk;
                }
            }
        }
        cout<<fixed<<setprecision(3)<<ans<<endl;
    }
    return 0;
}

UVa 1225(Digit Counting)
https://vjudge.net/problem/UVA-1225

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N,a[10];cin>>N;
    while(N--){
        memset(a,0,sizeof a);
        int n;cin>>n;
        for(int i=1;i<=n;i++){
            int kk=i;
            while(kk){
                a[kk%10]++;
                kk/=10;
            }
        }
        for(int i=0;i<10;i++){
            cout<<a[i];
            if(i==9)cout<<endl;
            else cout<<" ";
        }
    }
    return 0;
}

UVa 455(Periodic Strings)
https://vjudge.net/problem/UVA-455

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N;cin>>N;
    while(N--){
        string s;cin>>s;
        for(int i=1;i<=s.length();i++){
            if(s.length()%i)continue;
            bool flag=true;
            for(int j=0;j+i<s.length();j++){
                if(s[j]!=s[j+i]){flag=false;break;}
            }
            if(flag){
                cout<<i<<endl;
                if(N)cout<<endl;
                break;
            }
        }
    }
    return 0;
}

UVa 227(Puzzle)
https://vjudge.net/problem/UVA-227

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int dir[4][2]={-1,0,1,0,0,1,0,-1};
const char s[]="ABRL";
char a[10][10];
int main(){
    int t=0;
    while(gets(a[0])){
        if(a[0][0]=='Z')break;
        if(t)puts("");
        int m=0,n=0;
        rep(i,0,4){
            if(i)gets(a[i]);
            rep(j,0,4){
                if(a[i][j]==' '||a[i][j]==0){
                    a[i][j]=' ';
                    m=i,n=j;
                }
            }
        }
        bool flag=true;
        while(true){
            char c=getchar();
            if(c=='0')break;
            bool q=isspace(c);
            rep(i,0,3){
                if(!flag)break;
                if(c==s[i]){
                    q=true;
                    int x=m+dir[i][0],y=n+dir[i][1];
                    if (x<0||x>4||y<0||y>4){
                        flag=false;
                        break;
                    }
                    a[m][n]=a[x][y];
                    a[x][y]=' ';
                    m=x,n=y;
                }
            }
            if(!q)flag=false;
        }
        printf("Puzzle #%d:\n",++t);
        if(flag){
            rep(i,0,4){
                rep(j,0,4){
                    if(j)printf(" ");
                    printf("%c",a[i][j]);
                }
                printf("\n");
            }
        }
        else puts("This puzzle has no final configuration.");
        getchar();
    }
    return 0;
}

UVa 232(Crossword Answers)
https://vjudge.net/problem/UVA-232

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
typedef long long ll;
using namespace std;
struct node{
    int x,y,r,c;
}st[111];
char MAP[12][12];
int n,m,Case;
int main(){
    while(scanf("%d",&n),n){
        scanf("%d",&m);
        rep(i,0,n)scanf("%s",MAP[i]);
        int num=1;
        rep(i,0,n){
            rep(j,0,m){
                if(MAP[i][j]!='*'){
                    if((i-1)<0||(j-1)<0||MAP[i-1][j]=='*'||MAP[i][j-1]=='*'){
                        st[num].x=i;
                        st[num].y=j;
                        if((j-1)<0||MAP[i][j-1]=='*')st[num].r=1;
                        else st[num].r=0;
                        if((i-1)<0||MAP[i-1][j]=='*')st[num].c=1;
                        else st[num].c=0;
                        num++;
                    }
                }
            }
        }
        if(Case)puts("");
        printf("puzzle #%d:\nAcross\n",++Case);
        rep(i,1,num){
            if(st[i].r){
                printf("%3d.",i);
                rep(j,st[i].y,m){
                    if(MAP[st[i].x][j]=='*')break;
                    printf("%c",MAP[st[i].x][j]);
                }
                printf("\n");
            }
        }
        puts("Down");
        rep(i,0,num){
            if(st[i].c){
                printf("%3d.",i);
                rep(j,st[i].x,n){
                    if(MAP[j][ st[i].y ]=='*')break;
                    printf("%c",MAP[j][st[i].y]);
                }
                printf("\n");
            }
        }
    }
    return 0;
}

Uva 1368(DNA Consensus String)
https://vjudge.net/problem/UVA-1368

#include<bits/stdc++.h>
using namespace std;
string a[55],ans;
int main(){
    int T;cin>>T;
    while(T--){
        ans="";
        int m,n;cin>>m>>n;
        for(int i=0;i<m;i++)cin>>a[i];
        int dis=0;
        for(int i=0;i<n;i++){
            int A=0,T=0,G=0,C=0;
            for(int j=0;j<m;j++){
                if(a[j][i]=='A')A++;
                if(a[j][i]=='C')C++;
                if(a[j][i]=='G')G++;
                if(a[j][i]=='T')T++;
            }
            int M=max(A,max(C,max(G,T)));
            if(M==A)ans+='A',dis+=C+G+T;
            else if(M==C)ans+='C',dis+=A+G+T;
            else if(M==G)ans+='G',dis+=A+C+T;
            else if(M==T)ans+='T',dis+=A+C+G;
        }
        cout<<ans<<endl<<dis<<endl;
    }
    return 0;
}

UVa 202(Repeating Decimals)
https://cn.vjudge.net/problem/UVA-202
有点恶心,非要这样输出干啥!

#include<bits/stdc++.h>
using namespace std;
int a[3010],b[3010],vis[3010];
int main(){
    int n,m,t;
    while(cin>>n>>m){
        t=n;
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        memset(vis,0,sizeof vis);
        int cnt=0;
        a[cnt++]=n/m;
        n=n%m;
        while(!vis[n]&&n){
            vis[n]=cnt;
            b[cnt]=n;
            a[cnt++]=10*n/m;
            n=10*n%m;
        }
        printf("%d/%d = %d",t,m,a[0]);
        printf(".");
        for(int i=1;i<cnt&&i<=50;i++){
            if(n&&b[i]==n)printf("(");
            printf("%d",a[i]);
        }
        if(!n)printf("(0");
        if(cnt>50)printf("...");
        printf(")\n");
        printf("   %d = number of digits in repeating cycle\n\n",n?cnt-vis[n]:1);
    }
    return 0;
}

UVa 10340(All in All)
https://vjudge.net/problem/UVA-10340

#include<bits/stdc++.h>
using namespace std;
string a,b;
int lena,lenb,cura,curb;
int main(){
    while(cin>>a>>b){
        lena=a.length(),lenb=b.length();
        cura=curb=0;
        while(cura<lena&&curb<lenb){
            if(a[cura]==b[curb])cura++,curb++;
            else curb++;
        }
        if(cura>=lena)puts("Yes");
        else puts("No");
    }
    return 0;
}

UVa 1587(Box)
https://vjudge.net/problem/UVA-1587

#include<bits/stdc++.h>
using namespace std;
set<int>st;
struct node{
    int x,y;
    bool get(){if(cin>>x>>y){st.insert(x),st.insert(y);if(x<y)swap(x,y);return true;}return false;}
    friend bool operator < (node A,node B){return A.x==B.x?A.y>B.y:A.x>B.x;}
    friend bool operator == (node A,node B){return A.x==B.x&&A.y==B.y;}
}a[6];
int main(){
    while(a[0].get()){
        for(int i=1;i<6;i++)a[i].get();
        if(st.size()<=3){
            sort(a,a+6);
            if(a[0]==a[1]&&a[2]==a[3]&&a[4]==a[5])cout<<"POSSIBLE"<<endl;
            else cout<<"IMPOSSIBLE"<<endl;
        }
        else cout<<"IMPOSSIBLE"<<endl;
        st.clear();
    }
    return 0;
}

UVa 1588(Kickdown)
https://vjudge.net/problem/UVA-1588

#include<bits/stdc++.h>
using namespace std;
string a,b;
int lena,lenb,MIN=0;
int main(){
    while(cin>>a>>b){
        lena=a.length(),lenb=b.length();
        if(lena<lenb)swap(a,b),swap(lena,lenb);
        MIN=lena+lenb;
        for(int i=0;i<lena+lenb;i++){
            bool flag=true;
            if(i<lenb)
            for(int j=0;j<=i;j++){
                if(a[lena-1-i+j]+b[j]-'0'>'3'){flag=false;break;}
            }
            else if(i<lena)
            for(int j=0;j<lenb;j++){
                if(a[lena-1-i+j]+b[j]-'0'>'3'){flag=false;break;}
            }
            else
            for(int j=i-lena;j<lenb;j++){
                if(a[j-i+lena]+b[j]-'0'>'3'){flag=false;break;}
            }
            if(flag)
                if(i<lenb)MIN=min(MIN,lena+lenb-1-i);
                else if(i<lena)MIN=lena;
                else MIN=min(MIN,i);
        }
        cout<<MIN<<endl;
    }
    return 0;
}

UVa 11809(Floating-Point Numbers)
https://vjudge.net/problem/UVA-11809

//参照网上思路,打表。
#include<bits/stdc++.h>
using namespace std;
#define eps 1e-4
#define rep(i,a,b) for(int i=a;i<=b;i++)
string in;
double M[20][40];
long long E[20][40];
int main(){
    rep(i,0,9)rep(j,1,30){
        double m=1-pow(2,-1-i),e=pow(2,j)-1;
        double t=log10(m)+e*log10(2);
        E[i][j]=t,M[i][j]=pow(10,t-E[i][j]);
    }
    while(cin>>in&&in!="0e0"){
        for(string::iterator i=in.begin();i!=in.end();i++)if(*i=='e')*i=' ';
        istringstream ss(in);
        double A;int B;
        ss>>A>>B;
        while(A<1)A*=10,B-=1;
        rep(i,0,9)rep(j,1,30){
            if(B==E[i][j]&&(fabs(A-M[i][j])<eps||fabs(A/10-M[i][j])<eps)){
                cout<<i<<' '<<j<<endl;
                break;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41635132/article/details/82318138