矩阵快速幂<求有向图路径为k的方案(每条边可以取多次)>

来源:互联网 发布:python 金融数据 编辑:程序博客网 时间:2024/06/10 21:37

刚开始把建立一个矩阵,用以表示任意两个顶点之间是否有边,如果有矩阵上就为1,反之为0。

那么此时如果 这个矩阵乘这个矩阵,意思就成了这个矩阵u到w长度为1的个数乘上w到v长度为1的个数,也就成了长度为2的个数的多少(边取得任意多次)。

此时得到的k=2的矩阵,这个矩阵乘长度为1的矩阵还是这个矩阵u到w长度为2的个数乘上w到v长度为1的个数,也就是长度为3的矩阵个数

这么乘可以用快速幂求出。



#include <iostream>#include <string.h>#include <stdio.h>using namespace std;const int MOD=1e4+7;struct ttt{    int map1[20][20];};int n;ttt mul(ttt &a,ttt &b){ //矩阵A*B    ttt c;    int i,j,k;    for(i=1;i<=n;i++){        for(j=1;j<=n;j++){            c.map1[i][j]=0;            for(k=1;k<=n;k++){                c.map1[i][j]+=a.map1[i][k]*b.map1[k][j];                c.map1[i][j]%=MOD;            }        }    }    return c;}ttt mul_self(ttt &a){    ttt b;    int i,j,k;    for(i=1;i<=n;i++)        for(j=1;j<=n;j++){           b.map1[i][j]=0;           for(k=1;k<=n;k++){                b.map1[i][j]+=a.map1[i][k]*a.map1[k][j];                b.map1[i][j]%=MOD;           }        }        return b;}ttt pow1(ttt &a,int k){    ttt b;    int i,j;    memset(b.map1,0,sizeof(b.map1));    for(i=1;i<=n;i++)        for(j=1;j<=n;j++)            if(i==j)                b.map1[i][j]=1;            while(k){                //cout << "k=" <<k <<endl;                if(k&1)                    b=mul(b,a);                    k=k>>1;                    a=mul_self(a);            }            return b;}int main(){    freopen("in.txt","r",stdin);    int i,j,k,l,f1,f2,f3,t1,t2,t3;    int r,c,m;    int a1,b1,c1;    int T;    ttt a;    memset(a.map1,0,sizeof(a.map1));    cin >> n >> m;//n个结点,m条边    for(i=1;i<=m;i++){        cin >>t1>> t2;        a.map1[t1][t2]=1;    }    a=pow1(a,2);    int sum1=0;    for(i=1;i<=n;i++)    for(j=1;j<=n;j++){        sum1+=a.map1[i][j];    }    cout << sum1 << endl;    return 0;}

A sequence of integers x1,  x2,  ...,  xk is called a "xor-sequence" if for every 1  ≤  i  ≤  k - 1 the number of ones in the binary representation of the number xi  xi  +  1's is a multiple of 3 and  for all 1 ≤ i ≤ k. The symbol  is used for the binary exclusive or operation.

wa了  long long是种玄学,tle有可能long long 导致

题意:把一个序列的整数if这些整数异或以后的the number of ones是3的倍数  ,这里这个集合是指可以重复选择,x1,x2,x3叫做xor序列,问最大序列长度为k 的结果

这个关系可以两两建立一个图,无向图(相当于有向图箭头2边都有),然后找长度为k-1的路径,也就是结点数为k

矩阵快速幂即可。

#include <iostream>#include <string.h>#include <stdio.h>using namespace std;const int MOD=1e9+7;typedef long long ll;struct ttt{    ll map1[120][120];};ll n;ttt mul(ttt &a,ttt &b){ //矩阵A*B    ttt c;    ll i,j,k;    for(i=1;i<=n;i++){        for(j=1;j<=n;j++){            c.map1[i][j]=0;            for(k=1;k<=n;k++){                c.map1[i][j]=(c.map1[i][j]+a.map1[i][k]*b.map1[k][j])%MOD;            }        }    }    return c;}ttt mul_self(ttt &a){    ttt b;    ll i,j,k;    for(i=1;i<=n;i++)        for(j=1;j<=n;j++){           b.map1[i][j]=0;           for(k=1;k<=n;k++){                b.map1[i][j]=(b.map1[i][j]+a.map1[i][k]*a.map1[k][j])%MOD;           }        }        return b;}ttt pow1(ttt &a,ll k){    ttt b;    ll i,j;    memset(b.map1,0,sizeof(b.map1));    for(i=1;i<=n;i++)        for(j=1;j<=n;j++)            if(i==j)                b.map1[i][j]=1;            while(k){                //cout << "k=" <<k <<endl;                if(k&1)                    b=mul(b,a);                    k=k>>1;                    a=mul_self(a);            }            return b;}ll qq[105];ll fun2(ll x){    ll t1=0;    while(x){        if(x%2==1)t1++;        x/=2;    }    if(t1%3==0)return 1;    else return 0;}int main(){   // freopen("in.txt","r",stdin);    ll i,j,k,l,f1,f2,f3,t1,t2,t3;    ll r,c,m;    ll a1,b1,c1;    ll T;    ttt a;    memset(a.map1,0,sizeof(a.map1));    cin >> n >> m;//n个结点,m条边    for(i=1;i<=n;i++){        cin >> qq[i];    }    if(m==1){        cout << n<< endl;return 0;    }    for(i=1;i<=n;i++)    for(j=1;j<=n;j++){        if(fun2(qq[i]^qq[j])==1)            a.map1[i][j]=1;    }    a=pow1(a,m-1);    long long sum1=0;    for(i=1;i<=n;i++)    for(j=1;j<=n;j++){        sum1+=a.map1[i][j];        sum1%=MOD;    }    cout << sum1 << endl;    return 0;}



阅读全文
0 0
原创粉丝点击