题目大意:
有N个人,手上有Ai个标记,该人可以向指定的K个人添加标记(自己标记不会少)。
当该人手上有奇数个标记的时候,拥有投票权。问,最后有多少人手中的票为奇数个。
思路。以输入样例一为例:
初始状态矩阵:A=|210|
状态转移矩阵为:
|111|
B=|001|
|100|
于是乎第一轮结束后的状态:(A*B+A)
第二轮结束后的状态为: (A*B+A)*B+(A*B+A)=> A*(B+E)*B+A*(B+E)=>A*(B+E)^2;
同样第三轮结束后:A*(B+E)^3
这样就是规律了;
另外还有注意的一点就是题中说当为奇数的时候有投票权,偶数没有投票权。
我们看看下面这个矩阵
|AB| * | EF | = | A*E+B*G A*F+B*H |
|GH|
到底代表什么意思呢?
我们可以这么看:
1有A次投票机会,每次机会分别投给1E票,2G票。2有B 次投票机会,每次机会分别投给1F票,2H票。
这样1得到的票为A*E+B*G
可以发现当ABEFGH中为偶数的时候,都是没有用的。
所以直接%2是正确的。再者利用了矩阵的结合律。这么分析完,敲敲就AC了。
发现我的代码可以rank10诶~哈哈
#include<iostream>
#include<string.h>
#include<map>
#define MAXN 222
using namespace std;typedef short ll;
struct node
{ll ma[MAXN][MAXN];void init(){memset(ma,0,sizeof(ma));}
}res,temp,L;
int allocp;
void init()
{allocp=0;res.init();temp.init();L.init();for( int i=0;i<MAXN;i++ )res.ma[i][i]=1;
}void set_Matrix()
{for( int i=0;i<allocp;i++ )temp.ma[i][i]++;
}node matriXmult( node a,node b )
{node c;memset( c.ma,0,sizeof(c.ma) );for( int i=0;i<allocp;i++ )for( int k=0;k<allocp;k++ )if( a.ma[i][k] )for( int j=0;j<allocp;j++ )c.ma[i][j]+=a.ma[i][k]*b.ma[k][j];for( int i=0;i<allocp;i++ )for( int j=0;j<allocp;j++ )c.ma[i][j]%=2;return c;
}void matrix_Power( int t )
{for( int i=0;i<31;i++ ){if( t&(1<<i) )res=matriXmult(res,temp);temp=matriXmult(temp,temp);}
}int main()
{int T,n,t,mark,list;string str1,str2;cin>>T;while( T-- ){init();map<string,int>map;map.clear();cin>>n>>t;while( n-- ){cin>>str1;if( map.find(str1)==map.end() )map[str1]=allocp++;cin>>mark>>list;L.ma[0][map[str1]]=mark;for( int i=0;i<list;i++ ){cin>>str2;if( map.find(str2)==map.end() )map[str2]=allocp++;temp.ma[map[str1]][map[str2]]++;}}t--;set_Matrix();matrix_Power(t);node kk;kk.init();for( int i=0;i<1;i++ )for( int j=0;j<allocp;j++ )for( int k=0;k<allocp;k++ )kk.ma[i][j]+=L.ma[i][k]*res.ma[k][j];int sum=0;for( int i=0;i<allocp;i++ )sum+=( kk.ma[0][i]%2 );cout<<sum<<endl;}return 0;
}
A有A张票,分别投给EE张,GG张。