[POJ2947]Widget Factory(高斯消元)

题目:

我是超链接

题意:

有n 种装饰物,m 个已知条件,每个已知条件的描述如下:
p start end
a1,a2……ap (1<=ai<=n)
第一行表示从星期start 到星期end 一共生产了p件装饰物(工作的天数为end-start+1+7*x,加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类)。规定每件装饰物至少生产3 天,最多生产9 天。问每种装饰物需要生产的天数。
如果没有解,则输出“Inconsistent data.”,如果有多解,则输出“Multiple solutions.”,如果只有唯一解,则输出每种装饰物需要生产的天数。

题解:

这个样子列出同余方程用高斯消元去解应该不难了吧
因为m和n不相同,如果某一项的系数为0,不能成为i的关键方程,我们应该选择把他换到最后,因为ta有可能是别的人的关键方程
而且正因为m是累加的,我们要保证a和b的这些项为0,每次清零就是必不可少的
还有也不能像以前一样一看到这一项没有系数而且b为0就判断很多解了,因为好多方程等着判断呢,万一后边有个无解的情况怎么办

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int mod=7;
int a[305][305],b[305],ans[305],n,m;
int ksm(int a,int k)
{
    int ans=1;
    for (;k;k>>=1,a=a*a%mod) 
      if (k&1) ans=ans*a%mod;
    return ans;
}
void gauss()
{
    for (int i=1;i<=n;i++)
    {
        int num=i;
        for (int j=i+1;j<=m;j++)
          if (a[num][i]<a[j][i]) num=j;
        if (num!=i)
        {
            for (int j=i;j<=n;j++)
              swap(a[num][j],a[i][j]);
            swap(b[num],b[i]);
        }
        else if (!a[i][i])
        {
            ++m;
            for (int j=i;j<=n;j++)
              swap(a[num][j],a[m][j]);
            swap(b[num],b[m]);
        }
        for (int j=i+1;j<=m;j++)
        {
            int t=a[j][i]*ksm(a[i][i],mod-2)%mod;
            for (int k=i;k<=n;k++)
              a[j][k]=(a[j][k]-a[i][k]*t%mod+mod)%mod;
            b[j]=(b[j]-t*b[i]%mod+mod)%mod;
        }
    }
    bool fff=0; 
    for (int i=n;i>=1;i--)
    {
        if (!a[i][i]) 
        {
            if (!b[i]) {fff=1;continue;}
            else {printf("Inconsistent data.\n");return;}
        }
        ans[i]=b[i]*ksm(a[i][i],mod-2)%mod;
        for (int j=1;j<i;j++)
          b[j]=(b[j]-ans[i]*a[j][i]%mod+mod)%mod;
    }
    for (int i=n+1;i<=m;i++)
    {
        int now=0;
        for (int j=1;j<=n;j++)
          now=(now+ans[j]*a[i][j]%mod)%mod;
        if (now!=b[i]) {printf("Inconsistent data.\n");return;}
    }
    if (fff) {printf("Multiple solutions.\n");return;}
    for (int i=1;i<=n;i++) 
    {
        if (ans[i]<=2) ans[i]+=mod;
        printf("%d ",ans[i]);
     //   printf("%d%c",ans[i]," \n"[i==n]);
    }
    printf("\n");
}
int main()
{
    char s[5],e[5];int x;
    while (scanf("%d%d",&n,&m) && n!=0)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(ans,0,sizeof(ans));
        for (int i=1;i<=m;i++)
        {
            int p,beg,en;scanf("%d",&p);scanf("%s",s);scanf("%s",e);
            if (s[0]=='M') beg=1;
            else if (s[0]=='W') beg=3;
            else if (s[0]=='F') beg=5;
            else if (s[0]=='T' && s[1]=='U') beg=2;
            else if (s[0]=='T' && s[1]=='H') beg=4;
            else if (s[0]=='S' && s[1]=='A') beg=6;
            else if (s[0]=='S' && s[1]=='U') beg=7;

            if (e[0]=='M') en=1;
            else if (e[0]=='W') en=3;
            else if (e[0]=='F') en=5;
            else if (e[0]=='T' && e[1]=='U') en=2;
            else if (e[0]=='T' && e[1]=='H') en=4;
            else if (e[0]=='S' && e[1]=='A') en=6;
            else if (e[0]=='S' && e[1]=='U') en=7;

            b[i]=(en-beg+1+mod)%mod;

            while (p--) scanf("%d",&x),a[i][x]++,a[i][x]%=mod;
        }
        gauss();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值