UVALive 7511 L - Multiplication Table 数学模拟题,暴力

给定一副表,问其是否合法。

思路:当全部是?的时候,是合法的。

如果不是,那么,就找到一个数字,把它拆成若干个a*b的形式,去判断其它点是否合法即可。

拆分数字的时候,只需要枚举到sqrt(n),因为肯定是两个小于sqrt n的数相乘得到的结果。

比如6=1*6 6=2*3 注意分解后,考虑调换顺序是否合法即可。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>

const int maxn = 1000+5;
struct data
{
    LL num;
    int flag;
} a[maxn][maxn];
struct coor
{
    int x,y;
    LL num;
} To_number[maxn*maxn];
int len_To_number;
int n,m;
void show ()
{
    for (int i=1; i<=n; ++i)
    {
        for (int j=1; j<=m; ++j)
        {
            if (a[i][j].flag)
                printf ("%I64d ",a[i][j].num);
            else printf ("? ");
        }
        printf ("\n");
    }
    return ;
}
int f;
int solve (int x,int y,LL num)
{
    LL end = (LL)sqrt(num+0.5);
    for (LL aa=1; aa<=end; ++aa)
    {
        if (num%aa != 0) continue;
        LL bb = num/aa;//公差是aa
        int k;
        if (aa>=x && bb>=y)
        {
            for (k=1; k<=len_To_number; ++k)
            {
                int tx = To_number[k].x - x;
                int ty = To_number[k].y - y;
                LL ta = aa+tx, tb = bb+ty;
                if (ta*tb != To_number[k].num) break;
            }
            if (k == len_To_number +1) return 1;
        }
        LL taa = aa;
        LL tbb = bb;
        swap(taa,tbb);
        //cout<<taa<<" "<<tbb<<"--"<<endl;
        if (taa>=x && tbb >= y)
        {
            for (k=1; k<=len_To_number; ++k)
            {
                int tx = To_number[k].x - x;
                int ty = To_number[k].y - y;
                LL ta = taa+tx, tb = tbb+ty;
                if (ta*tb != To_number[k].num) break;
            }
            if (k == len_To_number +1) return 1;
        }
    }
    return 0;
}
void work ()
{
    int allque = 1;
    scanf("%d%d",&n,&m);
    int bx,by;
    LL number;
    len_To_number = 0;
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j)
        {
            char str[25];
            scanf("%s",str+1);
            if (str[1]=='?') a[i][j].flag = 0;
            else
            {
                allque = 0;
                a[i][j].flag=1;
                int lenstr = strlen(str+1);
                a[i][j].num=0;
                for (int k=1; k<=lenstr; ++k)
                    a[i][j].num = a[i][j].num*10+str[k]-'0';
                bx=i;
                by=j;
                number=a[i][j].num;
                To_number[++len_To_number].num = a[i][j].num;
                To_number[len_To_number].x = i;
                To_number[len_To_number].y = j;
            }
        }
    //show();
    if (allque)
    {
        printf ("Case #%d: Yes\n",++f);
        return ;
    }
    if (solve(bx,by,number))
    {
        printf ("Case #%d: Yes\n",++f);
        return ;
    }
    else
    {
        printf ("Case #%d: No\n",++f);
        return ;
    }
}

int main()
{
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    scanf("%d",&t);
    while (t--) work();
    return 0;
}
View Code

另外,枚举两个点的话,满足这两个点的解,就是唯一的解。也可以枚举两个点,然后确定唯一的一个解,再去比较整个地图。

不过也没什么必要。速度差不多。因为很少这样的例子,使得枚举的时候有很多个数字是满足的。

posted on 2016-08-19 19:22  stupid_one  阅读(592)  评论(0编辑  收藏  举报

导航