【10.6】

1>矩阵取数

 简单dp+高精度

今天新尝试了结构体写高精度

//再写一个40位的高精度加法 
//以及一个高精度乘法
//我要写一个压缩成4位的!!! 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
const int N=83;
int d[N];

const int mod=10000;
struct hp
{
    int len,p[11];
    hp()//构造函数 
    {
        memset(p,0,sizeof(p));
        len=0;
    }
    void print()
    {
        printf("%d",p[len]);
        for(int i=len-1;i>0;i--)
        {
            if(!p[i])
                printf("0000");
            else
            {
                for(int k=10;k*p[i]<=mod;k*=10) printf("0");
                printf("%d",p[i]);
            } 
        }
    }     
}dp[N],bas[N],ans;
hp operator + (const hp &a,const hp &b)
{
    hp c;
    c.len =max(a.len ,b.len );
    int x=0;
    for(int i=1;i<=c.len ;i++)
    {
        c.p[i]=a.p[i] +b.p[i] +x;
        x=c.p[i] /mod;
        c.p[i] %=mod;
    }
    if(x) c.p[++c.len ] =x;
    return c;
}
hp operator *(const hp &a,const int &b)
{
    hp c;
    c.len =a.len ;
    int x=0;
    for(int i=1;i<=c.len ;i++)
    {
        c.p[i]=a.p[i] *b +x;
        x=c.p[i] /mod;
        c.p[i] %=mod;
    }
    while(x)
        c.p[++c.len ] =x%mod,x/=mod;
    return c;
}
hp max(const hp &a,const hp &b)
{
    if(a.len !=b.len )
        return a.len >b.len ?a :b;
    
    for(int i=a.len ;i;i--)
        if(a.p[i] !=b.p[i] )
            return a.p[i] >b.p[i] ?a :b;
    return a;
}

void prepare()
{
    bas[0].p[++bas[0].len ] =1;
    for(int i=1;i<=m;i++)
        bas[i] =bas[i-1] *2;
}
void DP()
{
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=m;i++)
    {
        for(int j=i;j;j--)
            dp[j]=max(dp[j] + bas[i]*d[m-i+j+1] ,dp[j-1] + bas[i]*d[j]);
        dp[0] = dp[0] + bas[i]*d[m-i+1];
    }
    hp t=dp[0];
    for(int i=1;i<=m;i++) t= max(t,dp[i]);
    ans = ans+t;
}

int main()
{
    scanf("%d%d",&n,&m);
    prepare();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            scanf("%d",&d[j]);
        DP();
    }
    
    ans.print() ;
    return 0;
}

2>hanoi双塔问题

一个简单的2^(n+1)-2,求高精度结果

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n;

const int mod=10000;
struct hp
{
    int len,p[30];
    hp()
    {
        memset(p,0,sizeof(p));
        len=0;
    }
    void print()
    {
        printf("%d",p[len]);
        for(int i=len-1;i>0;i--)
        {
            if(!p[i]) printf("0000");
            else
            {
                for(int k=10;k*p[i]<=mod;k*=10) printf("0");
                printf("%d",p[i]);
            }
        }
    }
};
hp operator * (const hp &a,int &b)
{
    hp c;
    c.len =a.len ;
    int x=0;
    for(int i=1;i<=c.len ;i++)
    {
        c.p[i] =a.p[i] *b +x;
        x=c.p[i] /mod;
        c.p[i] %=mod;
    }
    while(x) 
        c.p[++c.len ] =x%mod,x/=mod;
    return c;
}
hp operator - (const hp &a,const int &b)
{
    hp c=a;
    int pos=1;
    c.p[pos] -=b;
    while(c.p[pos] <0)
    {
        c.p[pos] +=mod; 
        c.p[++pos] --;
    }
    while(!c.p[c.len ] ) c.len --; 
    return c;
}

int main()
{
    scanf("%d",&n);
    if(n<=25)
        printf("%d\n",(1<<n+1)-2);
    else
    {
        hp ans;int t=2;
        ans.p[++ans.len ] =2;
        for(int i=1;i<=n;i++)
            ans= ans*t;
        ans=ans-2;
        ans.print() ;
    }
    
    return 0;
} 

3>组合数问题

一道提高组,但是是绿色的题

简简单单的一个递推+统一mod后计数,90

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define int long long
using namespace std;
int k,t;
int n,m;
const int N=2003;
int c[N][N];

void prepare()
{
    c[0][0]=1;
    c[1][0]=c[1][1]=1;
    for(int i=2;i<=2000;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=i;j++)
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
    }    
}

signed main()
{
    scanf("%lld%lld",&t,&k);
    prepare();
    while(t--)
    {
        int ans=0;
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)
            for(int j=min(m,i);j>=0;j--)
                if(!c[i][j]) ans++;
        printf("%lld\n",ans);
    }
    
    return 0;
}

然后......想不到最终优化居然是前缀和......

int c[N][N],tr[N][N];
//询问太多,树状数组不如前缀和 
void prepare()
{
    c[0][0]=1;
    c[1][0]=c[1][1]=1;
    for(int i=2;i<=2000;i++)
    {
        c[i][0]=1,c[i][i]=1;
        for(int j=1;j<i;j++)
        {
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
            if(!c[i][j]) tr[i][j]=1;
        }
    }    
    for(int i=2;i<=2000;i++)
        for(int j=1;j<=i;j++)
            tr[i][j]+=tr[i][j-1];
}

signed main()
{
    scanf("%lld%lld",&t,&k);
    prepare();
    while(t--)
    {
        int ans=0;
        scanf("%lld%lld",&n,&m);
        for(int i=2;i<=n;i++)
            ans+=tr[i][min(i,m)];
        printf("%lld\n",ans);
    }
    
    return 0;
}

4>2^k进制数

我好粗心啊,碰到一大堆乘啊除啊的时候,

忘了去估算最大的数组大小,不停的re一个点

组合数验证保狗命

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int k,w;
const int N=1000,mod=10000;
struct hp
{
    int len,p[60];
    hp()
    {
        memset(p,0,sizeof(p));
        len=0;
    }
}c[N],ans;
hp operator + (const hp &a,const hp &b)
{
    hp d;
    d.len =max(a.len ,b.len );
    int x=0;
    for(int i=1;i<=d.len ;i++)
    {
        d.p[i] =a.p[i] +b.p[i] +x;
        x=d.p[i] /mod; 
        d.p[i] %=mod; 
    }
    if(x) d.p[++d.len ] =x;
    return d;
}

void print()
{
    printf("%d",ans.p[ans.len ] );
    for(int i=ans.len -1;i>0;i--)
    {
        if(!ans.p[i] ) printf("0000");
        else 
        {
            for(int k=10;k*ans.p[i] <=mod;k*=10)
                printf("0");
            printf("%d",ans.p[i] );
        }
    } 
}
void get_c(int k)
{
    c[k].p[++c[k].len ] =1;
    for(int i=k-1;i;i--)
        c[i]=c[i-1]+c[i] ;
}

int main()
{
    scanf("%d%d",&k,&w);
    c[0].p[++c[0].len ] =1;
    int n1=1<<k,c1=w%k,c2,tt=w/k;
    c1=n1-(1<<c1),c2=n1-2;
    for(int i=1;i<c1;i++) 
        get_c(i);
    for(int i=c1;i<=c2;i++)
    {
        get_c(i);
        if(tt<=i) ans= ans+ c[tt];//加验证保狗命 
    }
    get_c(c2+1);
    c1=2,c2=min(w/k,c2+1);
    for(int i=c1;i<=c2;i++)
        ans = ans +c[i];
    
    print();
    return 0;
}

5>无序字母对

猜你喜欢

转载自www.cnblogs.com/xwww666666/p/11626868.html