题目是说有N面点师..每个面点师又有一些自己欣赏的面点师..每一轮的庆祝有投票权的面点师讲给自己所欣赏的所有面点师标记一笔.而当轮的投票权是说前面所有庆祝下来当前面点师的所得标记数总和为奇数时才有资格投票..题目最终是问在第t轮庆祝时,哪些面点师能够投票...值得注意的是题目初始是从第一天开始的..也就是初始的票数是第一轮的票数..若题目要求出第一天的投票权情况..就是输入的奇偶情况..第二天的..跑一遍关系后的奇偶..类推则要求第t天情况..是经过t-1次庆祝后的情况..
首先构造一个能体现投票关系的矩阵A,A[i][j]=1代表i会给j投票.为0则说i不会给j投票..令每次庆祝时每人的票数为T[ k ] = { x1,x2,x3..xn } 那么显然 T[k] = T[k-1] + T[k-1]*A 可以将这个式子进行转化:T[k]=T[k-1]*(E+A)到了这一步..就能用矩阵乘法求解了...T[t]=T[0]*(E+A)^(t-1).
这道题做完了觉得还是很基础的..但从这其中发现一些值得注意的问题...矩阵是可以放心进行结合律的..但是,交换律神马的..最好还是别乱碰..像本题..T[k-1]*(E+A)..反过来(E+A)*T[k-1] 是不一样的..一定切记啊...
Program:
#include<iostream> #include<string.h> #include<stdio.h> #include<map> using namespace std; struct node { short s[102][102]; }h,temp,_2M[32]; string s; char str[25]; map<string,int> mymap; node Matrix_Mul(node a,node b,int n) { int i,j,k; memset(temp.s,0,sizeof(temp.s)); for (k=1;k<=n;k++) for (i=1;i<=n;i++) if (a.s[i][k]) for (j=1;j<=n;j++) temp.s[i][j]=(temp.s[i][j]+a.s[i][k]*b.s[k][j])%2; return temp; } void Output_Matrix(node h,int n) { int i,j; for (i=1;i<=n;i++) { for (j=1;j<=n;j++) printf("%hd ",h.s[i][j]); printf("\n"); } printf("-----------------------\n"); return; } node getmatrix(node h,int n,int l) { int k,p,i; node T; k=p=1; _2M[0]=h; // Output_Matrix(_2M[0],n); for (p=1;p<=30;p++) { _2M[p]=Matrix_Mul(_2M[p-1],_2M[p-1],n); k*=2; // Output_Matrix(_2M[p],n); if (k>l) break; } memset(T.s,0,sizeof(T.s)); for (i=1;i<=n;i++) T.s[i][i]=1; while (l) { while (l<k) { k/=2; p--; } T=Matrix_Mul(T,_2M[p],n); l-=k; } return T; } int main() { int i,x,y,k,p,ans,t,n,l; node a; scanf("%d",&t); while (t--) { scanf("%d%d",&n,&l); memset(h.s,0,sizeof(h.s)); a=h; mymap.clear(); k=0; for (i=1;i<=n;i++) { scanf("%s",str); s=str; if (mymap.find(s)==mymap.end()) { k++; mymap[s]=k; } x=mymap[s]; scanf("%hd%d",&a.s[1][x],&p); a.s[1][x]%=2; while (p--) { scanf("%s",str); s=str; if (mymap.find(s)==mymap.end()) { k++; mymap[s]=k; } y=mymap[s]; h.s[x][y]=1; } } for (x=1;x<=n;x++) if (!h.s[x][x]) h.s[x][x]=1; else h.s[x][x]=0; h=getmatrix(h,n,l-1); h=Matrix_Mul(a,h,n); ans=0; for (i=1;i<=n;i++) ans+=h.s[1][i]; printf("%d\n",ans); } return 0; }