题解
- 题意
- 题解
- 分析
- Code
前言
调了好久,还是太菜了
题意
洛谷:
SP UVA
vjudge
SP UVA
题解
分析
转换一下,题目就是让我们解方程组:
{
∑
i
=
1
n
a
1
,
i
x
i
≡
b
1
(
m
o
d
7
)
∑
i
=
1
n
a
2
,
i
x
i
≡
b
2
(
m
o
d
7
)
⋯
∑
i
=
1
n
a
m
,
i
x
i
≡
b
m
(
m
o
d
7
)
\left\{\begin{matrix} \sum_{i=1}^na_{1,i}x_i\equiv b_1 \pmod 7 \\ \sum_{i=1}^na_{2,i}x_i\equiv b_2 \pmod 7 \\ \cdots \\ \sum_{i=1}^na_{m,i}x_i\equiv b_m \pmod 7 \end{matrix}\right.
⎩
⎨
⎧∑i=1na1,ixi≡b1(mod7)∑i=1na2,ixi≡b2(mod7)⋯∑i=1nam,ixi≡bm(mod7)
其中 a i , j a_{i,j} ai,j 表示第 i i i 条记录中零件 j j j 加工的次数, x i x_i xi 为所求, b i b_i bi 表示第 i i i 条记录的天数。
如果不是在模意义下进行,这就是个裸的高斯消元。(如果你还不会请左转)
那怎么办呢?
我们还是直接暴力消元,只不过我们得到的是:
{ y 1 x 1 ≡ b 1 ( m o d 7 ) y 2 x 2 ≡ b 2 ( m o d 7 ) ⋯ y m x m ≡ b m ( m o d 7 ) \left\{\begin{matrix} y_1 x_1\equiv b_1\pmod7\\ y_2 x_2\equiv b_2\pmod7\\ \cdots \\ y_m x_m\equiv b_m\pmod7 \end{matrix}\right. ⎩ ⎨ ⎧y1x1≡b1(mod7)y2x2≡b2(mod7)⋯ymxm≡bm(mod7)
那求一下逆元即可,注意答案有范围。
再说一下无解和无数组解的情况。
因为有 n n n 个未知数, m m m 组方程,所以判无数组解时判完未知数即可,而判无解时要判全部方程。
注意:如果 m > n m>n m>n,对于剩下的 m − n m-n m−n 个方程,我们只用判断最右边那一列是否为 0 0 0 即可。
Code
参考代码:
int qmi(int x,int y){
int res=1;
while(y>0){
if(y&1)
res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
void gauss(){
int o=0;
for(int i=1;i<=n;i++){
int p=0;
for(int j=1;j<=m;j++)
if(a[j][i]&&(j>=i||!a[j][j])){
p=j;
break;
}
if(!p)
continue;
swap(a[i],a[p]);
for(int j=1;j<=m;j++){
if(a[j][i]&&j!=i){
int x=a[j][i]*qmi(a[i][i],mod-2)%mod;
for(int k=i;k<=n+1;k++)
a[j][k]-=a[i][k]*x,a[j][k]%=mod,a[j][k]=(a[j][k]+mod)%mod;
}
}
}
bool ok=1;
/*for(int i=1;i<=m;i++)
for(int j=1;j<=n+1;j++){
cout<<a[i][j]<<(j==n+1?"\n":" ");
}*/
for(int i=1;i<=n;i++){
if(!a[i][i]){
if(a[i][n+1]){
cout<<"Inconsistent data.\n";
return ;
}
}
}
for(int i=n+1;i<=m;i++){
if(a[i][n+1]){
cout<<"Inconsistent data.\n";
return ;
}
}
for(int i=1;i<=n;i++){
if(!a[i][i]){
if(!a[i][n+1]){
cout<<"Multiple solutions.\n";
return ;
}
}
}
int ans;
for(int i=1;i<=n;i++){
ans=a[i][n+1]*qmi(a[i][i],mod-2)%mod;
if(ans<3)
ans+=7;
cout<<ans<<(i==n?"\n":" ");
}
}
signed main(){
IOS;
cou(0);
// freopen("1","w",stdout);
map<string,int>A;
A["SUN"]=1;
A["MON"]=2;
A["TUE"]=3;
A["WED"]=4;
A["THU"]=5;
A["FRI"]=6;
A["SAT"]=7;
while(cin>>n>>m&&n&&m){
memset(a,0,sizeof a);
for(int i=1;i<=m;i++){
string s1,s2;
cin>>k>>s1>>s2;
a[i][n+1]=((A[s2]-A[s1]+1)%mod+mod)%mod;
for(int j=1;j<=k;j++){
int x;
cin>>x;
a[i][x]++,a[i][x]%=mod;
}
}
/*for(int i=1;i<=m;i++)
for(int j=1;j<=n+1;j++){
cout<<a[i][j]<<(j==n+1?"\n":" ");
}*/
gauss();
}
return 0;
}
/*
3 4
1 SUN FRI
2
1 MON SAT
3
3 FRI SAT
2 3 2
3 MON TUE
2 2 1
0 0
//无解
//给了一组数据,真良心~~
*/