【POJ 3735】Training little cats(万万没想到の矩快)

来源:互联网 发布:php支付宝sdk集成 编辑:程序博客网 时间:2024/06/08 09:30

【POJ 3735】Training little cats(万万没想到の矩快)

题目大意:
n只猫编号1~n
3中操作:
g i:给i一粒花生
e i:i把得到的花生全部吃掉
s i j:i与j交换花生。

给出一个操作序列,包含k个操作。
问执行这个序列m次,最后n只猫各自拥有的花生数量。

一直在找循环节,写了个暴力对拍和数据生成器,结果死活找不到合适的循环。

之后问了问度娘……对啊!矩快啊!。。。
100*100,然后重复次数这么大,我在干什么……

矩阵的初始化挺有趣的,跟之前做过的dp的初始化略有不同,类似于在线初始化,不是预制好的。

根据k个操作,让转移矩阵不断变化。矩阵中除了1~n每只猫当前花生数量外,还要有一个位置,给’1’。每次g i的时候从这里拿。然后e i就是清空i这行,s i j就是把第i行和第j行互换。

搞完后交上去会TLE。因为k是100,所以满矩阵最多有100个位置有数,其余位置都是0,所以在做矩阵乘法的时候判断一下

        for(int k = 0; k <= len; ++k)            for(int i = 0; i <= len; ++i)                if(ans[i][k])                for(int j = 0; j <= len; ++j)                    tmp.ans[i][j] += ans[i][k]*a.ans[k][j];

代码后面晒了数据生成器和暴力对拍工具

代码如下:

#include <iostream>#include <cmath>#include <vector>#include <cstdlib>#include <cstdio>#include <climits>#include <ctime>#include <cstring>#include <queue>#include <stack>#include <list>#include <algorithm>#include <map>#include <set>#define LL long long#define Pr pair<int,int>#define fread(ch) freopen(ch,"r",stdin)#define fwrite(ch) freopen(ch,"w",stdout)using namespace std;const int INF = 0x3f3f3f3f;const int mod = 1e9+7;const double eps = 1e-8;const int maxn = 233;struct Matrix{    LL ans[maxn][maxn];    int len;    void init(int l,int k)    {        char opt[3];        int a,b;        len = l;        for(int i = 0; i <= len; ++i)             for(int j = 0; j <= len; ++j)                ans[i][j] = i==j;        while(k--)        {            scanf("%s",opt);            if(opt[0] == 'g')            {                scanf("%d",&a);                ans[a][0]++;            }            else if(opt[0] == 'e')            {                scanf("%d",&a);                memset(ans[a],0,sizeof(ans[a]));            }            else            {                scanf("%d%d",&a,&b);                for(int i = 0; i <= len; ++i)                    swap(ans[a][i],ans[b][i]);            }        }    }    void init(int l)    {        len = l;        for(int i = 0; i <= len; ++i)             for(int j = 0; j <= len; ++j)                ans[i][j] = i==j;    }    Matrix operator *(const struct Matrix a)const    {        Matrix tmp;        tmp.len = len;        memset(tmp.ans,0,sizeof(ans));        for(int k = 0; k <= len; ++k)            for(int i = 0; i <= len; ++i)                if(ans[i][k])                for(int j = 0; j <= len; ++j)                    tmp.ans[i][j] += ans[i][k]*a.ans[k][j];        return tmp;    }    void prt()    {        for(int i = 0; i <= len; ++i)        {            for(int j = 0; j <= len; ++j)            {                printf("%lld ",ans[i][j]);            }            puts("");        }        puts("---------");    }} mt,ans;int n,k;void Pow(LL b){    ans.init(n);    while(b)    {        if(b&1) ans = ans*mt;        b >>= 1;        mt = mt*mt;    }}int main(){    fread("in.in");    fwrite("my.out");    LL m;    while(~scanf("%d%lld%d",&n,&m,&k) && (n+m+k))    {        mt.init(n,k);        Pow(m);        for(int i = 1; i <= n; ++i)        {            if(i != 1) putchar(' ');            printf("%lld",ans.ans[i][0]);        }        puts("");    }    return 0;}

数据生成器:

#include <iostream>#include <cmath>#include <vector>#include <cstdlib>#include <cstdio>#include <climits>#include <ctime>#include <cstring>#include <queue>#include <stack>#include <list>#include <algorithm>#include <map>#include <set>#define LL long long#define Pr pair<int,int>#define fread(ch) freopen(ch,"r",stdin)#define fwrite(ch) freopen(ch,"w",stdout)using namespace std;const int INF = 0x3f3f3f3f;const int mod = 1e9+7;const double eps = 1e-8;const int maxn = 112345;int main(){    //fread("");    fwrite("in.in");    int n,m,k;    int t = 10;    srand(time(NULL));    while(t--)    {        n = 100;        m = 10000;        k = 100;        printf("%d %d %d\n",n,m,k);        srand(time(NULL));        while(k--)        {            int c = rand()%3;            if(c == 0)            {                printf("g %d\n",rand()%n+1);            }            else if(c == 1)            {                printf("e %d\n",rand()%n+1);            }            else printf("s %d %d\n",rand()%n+1,rand()%n+1);        }    }    puts("0 0 0");    return 0;}

对拍:

#include <iostream>#include <cmath>#include <vector>#include <cstdlib>#include <cstdio>#include <climits>#include <ctime>#include <cstring>#include <queue>#include <stack>#include <list>#include <algorithm>#include <map>#include <set>#define LL long long#define Pr pair<int,int>#define fread(ch) freopen(ch,"r",stdin)#define fwrite(ch) freopen(ch,"w",stdout)using namespace std;const int INF = 0x3f3f3f3f;const int mod = 1e9+7;const double eps = 1e-8;const int maxn = 112345;struct Action{    char opt[3];    int a,b;} act[233];LL n,m,k;LL ans[2][233];void cal(int pos){    for(int i = 0; i < k; ++i)    {        if(act[i].opt[0] == 'g') ans[pos][act[i].a]++;        else if(act[i].opt[0] == 'e') ans[pos][act[i].a] = 0;        else swap(ans[pos][act[i].a],ans[pos][act[i].b]);    }}int main(){    fread("in.in");    fwrite("out.out");    while(~scanf("%lld%lld%lld",&n,&m,&k) && (n+m+k))    {        for(int i = 0; i < k; ++i)        {            scanf("%s",act[i].opt);            scanf("%d",&act[i].a);            if(act[i].opt[0] == 's') scanf("%d",&act[i].b);        }        memset(ans,0,sizeof(ans));        while(m--)            cal(0);        for(int i = 1; i <= n; ++i)        {            if(i != 1) putchar(' ');            printf("%lld",ans[0][i]);        }        puts("");    }    return 0;}
0 0