2017-10-6 七道题

来源:互联网 发布:vbscript和vb 编辑:程序博客网 时间:2024/05/22 12:02

一、深搜,全排列和组合数

1、 全排列,没有重复元素
输入一行字母(长度小于等于10),输出:第一行输出全排列个数,从下一行开始按字典序输出这些字母所有可能的排列,每行一个。

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;int len,a[101];char ch[101];bool b[101];long long jc[50];void jiecheng(){    jc[0]=1;    for (long long i=1; i<=len; i++)        jc[i]=jc[i-1]*i;}void shuchu(){    for (int i=1; i<=len; i++)        putchar(ch[a[i]-1]);    printf("\n");}void dfs(int num){    for (int i=1; i<=len; i++)        if (!b[i])        {            b[i]=true;            a[num]=i;            if (num==len) shuchu();            else dfs(num+1);            b[i]=false;        }}int main(){    freopen("pl.in","r",stdin);    freopen("pl.out","w",stdout);    cin>>ch;    len=strlen(ch);    jiecheng();    sort(ch,ch+len);    printf("%lld\n",jc[len]);    dfs(1);    return 0;}

2、 全排列,没重复元素
桶排的思路,统计每个单词出现的个数。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int len,m,sum=1,a[101],to[200],tot;//to数组开小 char ch[101],c[36288][10];//二维数组c用来判重bool b[101];int jc[101];void jiecheng(){    jc[0]=1;    for (int i=1; i<=len; i++)        jc[i]=jc[i-1]*i;}void shuchu(){    for (int i=1; i<=len; i++)        putchar(a[i]);    printf("\n");}void dfs(int num){    for (int i='a'; i<='z'; i++)        if (to[i])        {            a[num]=i;            to[i]--;            if (num==len) shuchu();            else dfs(num+1);            to[i]++;        }}int main(){    freopen("plt.in","r",stdin);    freopen("plt.out","w",stdout);    scanf("%s",ch);    len=strlen(ch);    jiecheng();    for (int i=0; i<len; i++)        to[ch[i]]++;    for (int i='a'; i<='z'; i++)        if (to[i]) sum*=jc[to[i]];    int ans=jc[len]/sum;//方法数    printf("%d\n",ans);    dfs(1);    return 0;}

3、求组合,没有重复元素

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int len,m,a[20],tot;char ch[20];bool b[20];long long c[101][101];void Com(){    for (int i=1; i<=len; i++) c[i][0]=c[i][i]=1;    for (int i=1; i<=len; i++)        for (int j=1; j<=i; j++)            c[i][j]=c[i-1][j]+c[i-1][j-1];}void print(){    for (int i=1; i<=m; i++)        putchar(ch[a[i]-1]);    printf("\n");}void dfs0(int num){    for (int i=1; i<=len; i++)        if (!b[i]&&i>a[num-1])        {            a[num]=i;            b[i]=true;            if (num==m) tot++;            else dfs0(num+1);            b[i]=false;        }}void dfs(int num){    for (int i=1; i<=len; i++)        if (!b[i]&&i>a[num-1])        {            a[num]=i;            b[i]=true;            if (num==m) print();            else dfs(num+1);            b[i]=false;        }}int main(){    freopen("zh.in","r",stdin);    freopen("zh.out","w",stdout);    scanf("%s",ch);    scanf("%d",&m);    len=strlen(ch);    sort(ch,ch+len);    Com();    dfs0(1);    printf("%d\n",tot);    dfs(1);    return 0;}

4、求组合,有重复元素

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int len,m,sum=1,a[101],to[200],tot;//to数组开小 char ch[101];bool b[101];int jc[101];int c[101][101];void jiecheng(){    jc[0]=1;    for (int i=1; i<=len; i++)        jc[i]=jc[i-1]*i;}void Com(){    for (int i=1; i<=len; i++) c[i][0]=c[i][i]=1;    for (int i=1; i<=len; i++)        for (int j=1; j<=i; j++)            c[i][j]=c[i-1][j]+c[i-1][j-1];}void shuchu(){    for (int i=1; i<=m; i++)        putchar(a[i]);    printf("\n");}void dfs0(int num){    for (int i='a'; i<='z'; i++)        if (to[i]&&i>=a[num-1])        {            a[num]=i;            to[i]--;            if (num==m) tot++;            else dfs0(num+1);            to[i]++;        }}void dfs(int num){    for (int i='a'; i<='z'; i++)        if (to[i]&&i>=a[num-1])        {            a[num]=i;            to[i]--;            if (num==m) shuchu();            else dfs(num+1);            to[i]++;        }}int main(){    freopen("zht.in","r",stdin);    freopen("zht.out","w",stdout);    scanf("%s",ch);    scanf("%d",&m);    len=strlen(ch);    jiecheng();    for (int i=0; i<len; i++)        to[ch[i]]++;    for (int i='a'; i<='z'; i++)        if (to[i]) sum*=jc[to[i]];    dfs0(1);    printf("%d\n",tot);    dfs(1);    return 0;}

二、数论

5、下一个全排列

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;int len;char ch[520];int main(){    freopen("np.in","r",stdin);    freopen("np.out","w",stdout);    int flag=0;    cin>>ch;    len=strlen(ch);    for (int i=len-1; i>=0; i--)    {        if (ch[i-1]>ch[i])        {flag++; continue;}//找到第一个下降的         if (flag==len-1) break;        int t=i;        for (int j=i; j<len; j++)//在它后面找一个比它大最小的             if (ch[i-1]<ch[j]&&ch[j]<ch[t]) t=j;        swap(ch[i-1],ch[t]);        sort(ch+i,ch+len);        break;    }    if (flag==len-1)        for (int i=len-1; i>=0; i--) putchar(ch[i]);    else printf("%s",ch);    return 0;}

6、求某个排列的序号

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;char ch[50];int len;long long jc[50],sum;int judge(int x)//ch[x]位置后有多少个字母小于ch[x] {    int tot=0;    for (int i=x+1; i<len; i++)        if (ch[x]>ch[i]) tot++;    return tot;}void jiecheng(){    jc[0]=1;    for (long long i=1; i<=len; i++)        jc[i]=jc[i-1]*i;}int main(){    freopen("bh.in","r",stdin);    freopen("bh.out","w",stdout);    scanf("%s",ch);    len=strlen(ch);    jiecheng();    for (int i=1; i<len; i++)        sum+=judge(i-1)*jc[len-i];    printf("%lld",sum+1);    return 0;}

7、第m个全排列

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;int len,m,a[101],small;//small:ch[i]后面有几个比ch[i]小的字母 long long total,jc[101];char ch[101],ans[101];bool b[101];void jiecheng(){    jc[0]=1;    for (long long i=1; i<=len; i++)        jc[i]=jc[i-1]*i;}int main(){    freopen("xh.in","r",stdin);    freopen("xh.out","w",stdout);    scanf("%s",ch);    scanf("%d",&m);    len=strlen(ch);    jiecheng();    sort(ch,ch+len);    m--;    for (int i=0; i<len; i++)    {        for (int j=len; j>=0; j--)            if (j*jc[len-i-1]<=m)             { m-=j*jc[len-i-1]; small=j; break;}//贪心 忘记了break         int t=0;        for (int j=0; j<len; j++)            if (!b[j])//在没用过的字母里面找第small大的(b[i]X)                if (t++==small) {small=j; break;}        ans[i]=ch[small];        b[small]=true;    }    printf("%s",ans);    return 0;}

七道这么水的题都要打上一天。loli说这种题做不了怎么拿省一(省三)。马上就要被loli踢出去了。。
“怕是失了志、”
代码能力,需要马上并迫切地提升。noip可能并不需要非常高深的算法,但是需要具备把自己的想法转化成代码的能力。多刷题多总结多思考,之前欠下的债总是要还的。