【CF832E】Vasya and Shifts
题意:给你n个5进制数a1,a2...an,每个数都有4个,有m个询问,每次给你一个数bi,要你用a中的数进行不进位的加法来得到bi,求方案数。
题解:先考虑一个询问,我们设未知数xi表示第i个数用了几个,那么可以列出方程组。如果方程组无解,那么答案为0;否则答案就是5^(自由元的个数)。
多组询问呢?直接将全部询问构成的矩阵扔到系数矩阵的右面然后消元就行了。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n,m,q,cnt; long long ans; char str[510]; int v[510][1010],imp[510]; int ine(int x) { return x*x*x%5; } int main() { scanf("%d%d",&n,&m); int i,j,k,now; for(i=1;i<=n;i++) { scanf("%s",str+1); for(j=1;j<=m;j++) v[j][i]=str[j]-‘a‘; } scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%s",str+1); for(j=1;j<=m;j++) v[j][n+i]=str[j]-‘a‘; } for(now=i=1;i<=m&&now<=n;i++,now++) { for(j=i+1;j<=m;j++) if(v[j][now]>v[i][now]) for(k=now;k<=n+q;k++) swap(v[j][k],v[i][k]); while(!v[i][now]&&now<=n) now++,cnt++; if(now>n) break; int t=ine(v[i][now]); for(k=now;k<=n+q;k++) v[i][k]=v[i][k]*t%5; for(j=i+1;j<=m;j++) if(v[j][now]) { t=v[j][now]; for(k=now;k<=n+q;k++) v[j][k]=((v[j][k]-t*v[i][k])%5+5)%5; } } if(now<=n) cnt+=n-now+1; for(;i<=m;i++) for(k=n+1;k<=n+q;k++) if(v[i][k]) imp[k-n]=1; for(ans=1,i=1;i<=cnt;i++) ans=ans*5%1000000007; for(i=1;i<=q;i++) printf("%I64d\n",imp[i]?0ll:ans); return 0; } //2 1 c b 1 a
时间: 2024-10-07 07:44:04