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>无序字母对