您的位置:首页 > 其它

acm 一周训练总结

2016-08-06 20:36 127 查看
一周  总的来说 状压dp + 数学

状压dp 的概念就是 

根据 所选物体的多种状态 将其压缩为一个二进制形式

比如 一行

101 表示1开0关1开  这是一种状态,

dp 找状态转移方程

两种状态不能重合  在选取可以的 逐步dp 我认为 这个过程类似搜索  dfs 逐步找适合的 最后枚举 。

我是看例题

看懂的 这里 

有n门课,每门课有截止时间和完成所需的时间,如果超过规定时间完成,每超过一天就会扣1分,问怎样安排做作业的顺序才能使得所扣的分最小

思路:因为最多只有15门课程,可以使用二进制来表示所有完成的状况

例如5,二进制位101,代表第一门和第三门完成了,第二门没有完成,那么我们可以枚举1~1<<n便可以得出所有的状态

然后对于每一门而言,其状态是t = 1<<i,我们看这门在现在的状态s下是不是完成,可以通过判断s&t是否为1来得到

当得出t属于s状态的时候,我们便可以进行DP了,在DP的时候要记录路径,方便之后的输出

就是这个 例题
状压dp的 内容主要是找状态 

找状态加状态转移方程 

需要注意的 是

n个位置

1<<n 得数是1后面n个0

这是 枚举的关键

a了 8个题就开始搞数学了 

听学长的意见 

这是个组队游戏

还得有人搞数学

高斯消元法

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<cmath>
using namespace std;
double g[1000][1000];
double jie[10000];
int n,m;
void solve()
{
int i,j;
int k;
int s;
for(i=1;i<=n;i++)
{
int r=i;
for(j=i+1;j<=n;j++)
{
if(abs(g[j][i])>abs(g[r][i])) r=j;
}
if(r!=i)
for(s=1;s<=m+1;s++) swap(g[i][s],g[r][s]);
for(k=i+1;k<=n;k++)
{
double f=g[k][i]/g[i][i];
for(j=1;j<=m+1;j++)
g[k][j]-=f*g[i][j];
}
}
for(i=1;i<=n;i++)
{
cout<<endl;
for(k=1;k<i;k++)
cout<<" ";
for(j=i;j<=m;j++)
cout<<g[i][j]<<" ";
}
cout<<endl;
for(i=n;i>=1;i--)
{ double sum=g[i][m+1];
for(j=m;j>=i+1;j--)
sum-=jie[j]*g[i][j];
jie[i]=sum/g[i][i];
}
}
int main()
{

int i,j;
while(cin>>n>>m)
{
for(i=1;i<=n;i++)
for(j=1;j<=m+1;j++)
cin>>g[i][j];
solve();
for(i=1;i<=n;i++)
cout<<jie[i]<<endl;
}
}
这个是
高斯消元法最经典的 关灯

看了好久看懂了。

学会递推的矩阵快速幂 。

斐波那契数列

就是最经典的矩阵快速幂

#include<iostream>

#include<cstdio>

using namespace std;

int n,a[2][2],b[2][2];

void mul(int a[2][2],int b[2][2],int ans[2][2])

{

     int t[2][2];

     for(int i=0;i<2;i++)

        for(int j=0;j<2;j++)

        {

                t[i][j]=0;

                for(int k=0;k<2;k++)

                t[i][j]=(t[i][j]+a[i][k]*b[k][j])%10000;

        }

     for(int i=0;i<2;i++)

        for(int j=0;j<2;j++)

           ans[i][j]=t[i][j];    

 }

int main()

{

    while(scanf("%d",&n))

    {

        if(n==-1)return 0;

        a[0][0]=a[0][1]=a[1][0]=1;a[1][1]=0;

        b[0][0]=b[1][1]=1;

        b[1][0]=b[0][1]=0;

        while(n)

        {

                if(n&1)mul(a,b,b);

                n>>=1;

                mul(a,a,a);

        } 

        printf("%d\n",b[1][0]); 

    }

}

          

这是斐波那契数列 利用矩阵快速幂 解决方法

 比如

矩阵

AAAAAAAA

可以分成

AAAA

*AAAA

111111111111111111

占一个

矩阵快速幂

欧拉函数

奇妙的容斥原理

同余莫算数

杨辉三角

等等

一个文件夹了整理的

最后一句  矩阵真神奇!!!!!!!!!!!!!!!!!!!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: