K. Guanguan's Happy water
按着题解打了代码:高斯消元 和 矩阵乘法... 因为很久没有做高斯消元的题了 想着顺便做做
然后 然后没细想 就先做了 然后就T了 然后 然后发现牛客群说 题解说的时间复杂度是1e9.....
#include#define debug printf("!"); using namespace std; const int maxn=1e5+50; const int mod=1e9+7; typedef long long ll; ll a[210],f[210]; ll kpow(ll a,ll b) { ll ans=1,base=a; while(b) { if(b&1)ans=ans*base%mod; base=base*base%mod; b>>=1; } return ans; } ///高斯消元模板 const int Max_M=75; ///m个方程,n个变量 const int Max_N=75; ll m,n; ll Aug[Max_M][Max_N+1]; ///增广矩阵 bool free_x[Max_N]; ///判断是否是不确定的变元 ll x[Max_N]; ///解集 /** 返回值: -1 无解 0 有且仅有一个解 >=1 有多个解,根据free_x判断哪些是不确定的解 */ int Gauss() { int i,j; int row,col,max_r; for(row=0,col=0;row ) { max_r=row; for(i=row+1;i ///找到当前列所有行中的最大值(做除法时减小误差) { if(fabs(Aug[i][col])-fabs(Aug[max_r][col])>0) max_r=i; } if(max_r!=row) ///将该行与当前行交换 { for(j=row;j 1;j++) swap(Aug[max_r][j],Aug[row][j]); } if(Aug[row][col]==0) ///当前列row行以下全为0(包括row行) { row--; continue; } for(i=row+1;i ) { if(Aug[i][col]==0)continue; int ta=Aug[i][col]*kpow(Aug[row][col],mod-2)%mod; for(j=col;j 1;j++) Aug[i][j]=(Aug[i][j]-Aug[row][j]*ta%mod+mod)%mod; } } /* kkkek: 最后化得的增广矩阵: for(i=0;i */ for(i=row;i col=n存在0...0,a的情况,无解 { if(Aug[i][col])return -1; } if(row < n) ///存在0...0,0的情况,有多个解,自由变元个数为n-row个 { for(i=row-1;i>=0;i--) { int free_num=0; ///自由变元的个数 int free_index; ///自由变元的序号 for(j=0;j/// ) { if(Aug[i][j]!=0&&free_x[j]) free_num++,free_index=j; } if(free_num>1)continue; ///该行中的不确定的变元的个数超过1个,无法求解,它们仍然为不确定的变元 ///只有一个不确定的变元free_index,可以求解出该变元,且该变元是确定的 int tmp=Aug[i][n]; for(j=0;j ) { if(Aug[i][j]!=0&&j!=free_index) tmp=(tmp-Aug[i][j]*x[j]%mod+mod)%mod; } x[free_index]=tmp*kpow(Aug[i][free_index],mod-2)%mod; free_x[free_index]=false; } return n-row; } ///有且仅有一个解,严格的上三角矩阵(n==m) for(i=n-1;i>=0;i--) { int tmp=Aug[i][n]; for(j=i+1;j ) if(Aug[i][j]!=0) tmp=(tmp-Aug[i][j]*x[j]%mod+mod)%mod; x[i]=tmp*kpow(Aug[i][i],mod-2)%mod; } return 0; } ///模板结束 ll S[210][210]; //矩阵乘法 const int N=210; ll tmp[N][N]; void multi(ll aa[][N],ll b[][N],ll n) { memset(tmp,0,sizeof tmp); for(int i=0;i ) for(int j=0;j ) for(int k=0;k ) tmp[i][j]=(tmp[i][j]+aa[i][k]*b[k][j]%mod)%mod; for(int i=0;i ) for(int j=0;j ) aa[i][j]=tmp[i][j]; } ll res[N][N]; void Pow(ll aa[][N],ll b,ll n) { memset(res,0,sizeof res); for(int i=0;i 1; while(b) { if(b&1) multi(res,aa,n);//res=res*a;复制直接在multi里面实现了; multi(aa,aa,n);//a=a*a b>>=1; } for(int i=0;i ) for(int j=0;j ) aa[i][j]=res[i][j]%mod; } // ll A[210][210]; int main() { int T; scanf("%d",&T); while(T--) { memset(Aug,0,sizeof(Aug)); memset(x,0,sizeof(x)); memset(free_x,0,sizeof(free_x)); ll k,N,i,j,ans=0; scanf("%lld%lld",&k,&N); n=m=k; for(i=1;i<=k;i++) { scanf("%lld",&a[i]); f[i]=a[i]; ans=(ans+a[i])%mod; } for(i=k+1;i<=2*k;i++) scanf("%lld",&f[i]); for(i=k;i<2*k;i++) { Aug[k-i][k]=f[i+1]; for(j=i;j>i-k;j--) { Aug[k-i][i-j]=f[j]; } } Gauss(); // printf("**P:");for(i=0;i memset(S,0,sizeof(S)); for(i=0;i ][i]=x[i]; for(i=0;i0 ) { if(i)S[i][i-1]=1; for(j=0;j ) S[i][i+k]=1; S[i+k][i+k]=1; } Pow(S,N-k+1,k*2); // printf("##\n"); // for(i=0;i<2*k;i++) // { // for(j=0;j<2*k;j++) // printf("%lld ",S[i][j]); // printf("\n"); // }printf("##\n"); for(i=0;i ) { for(j=0;j ) { A[i][j]=S[i][j+k]; if(i==j)A[i][j]--; // printf("%lld ",A[i][j]); } // printf("\n"); }//A+A^2+……+A^N-k for(i=0;i ) { ans=(ans+A[0][i]*f[k-i]%mod)%mod; } printf("%lld\n",ans); } }
然后在我T了之后,我去看了牛客群。看到有人说:i大于k f[i]都不会变。
然后 然后就 我就大概能理解为什么这么麻烦的题这么多人过。
哎....
#includeusing namespace std; typedef long long ll; #define debug printf("!"); const int mod=1e9+7; const int maxn=1e3+50; int main() { int T; scanf("%d",&T); while(T--) { ll k,n,ans=0,i,t,r; scanf("%lld%lld",&k,&n); for(i=1;i<=k;i++) { scanf("%lld\n",&t); ans=(ans+t)%mod; } r=t; for(i=1;i<=k;i++)scanf("%d",&t); ans=(ans+(n-k)%mod*r)%mod; printf("%lld\n",ans); } }
哎....