Regionals 2015 >> Asia - EC Final>> Multiplication Table

/*由两个点的值及相对位置求解左上角点的坐标,解的判断很麻烦,wr*/
#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll M=1e9,N=1e3+10;
struct point
{
    int x,y,v;
}pq[N*N];
int n,m,k;
int jud(ll x,ll y)
{
    int x0=pq[0].x,y0=pq[0].y;
    for(int i=2;i<k;i++)
    {
        int dx=pq[i].x-x0,dy=pq[i].y-y0;
        if((x+dx)*(x+dy)!=pq[i].v) return 0;
    }
    return 1;
}
void read()
{
     k=0;
     char ch;
     scanf("%d%d",&n,&m);getchar();
     for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
      {
        scanf("%c",&ch);
        if(ch=='?') {getchar();continue;}
        int num=ch-'0';
        while(ch=getchar())
        {
            if(!(ch>='0'&&ch<='9')) break;
            num=num*10+(ch-'0');
        }
        pq[k].x=i;pq[k].y=j;pq[k++].v=num;
      }
}
int main()
{

   int t,ca=1;
   scanf("%d",&t);
   while(t--)
   {
       read();
       printf("Case #%d: ",ca++);
        if(k==0) {printf("Yes\n");continue;}
        if(k==1)
        {
          int flag=0;
          for(int i=1;i*i<=pq[0].v;i++)
          {
              if(pq[0].v%i==0&&pq[0].v/i>=pq[0].y&&i>=pq[0].x) {flag=1;printf("Yes\n");break;}
              if(pq[0].v%i==0&&pq[0].v/i>=pq[0].x&&i>=pq[0].y){flag=1;printf("Yes\n");break;}
          }
          if(flag) continue;
          printf("No\n");continue;
        }

        int n1=pq[1].x-pq[0].x,m1=pq[1].y-pq[0].y;
        int c1=pq[0].v,c2=pq[1].v;
        ll c=(c2-c1-n1*m1)*(c2-c1-n1*m1)-4*n1*m1*c1;//b^2-4ac
        if(c<0) {printf("No\n");continue;}
        double temp=sqrt(c);
        if(temp-(ll)temp>0.00000001) {printf("No\n");continue;}
        ll x1,y1,x2,y2;
        if(pq[0].x==pq[1].x)
        {
            if((c2-c1)>=m&&(c2-c1)%m1==0)
            {
               x1=(c2-c1)/m1;
               if(c2>=x1&&c2%x1==0)
               {
                   y1=c2/x1;
                   if(jud(x1,y1)){printf("Yes\n");continue;}
               }
            }
            printf("No\n");
            continue;
        }
        if(pq[0].y==pq[1].y)
        {
            if((c2-c1)>=n1&&(c2-c1)%n1==0)
            {
               y1=(c2-c1)/n1;
               if(c2>=y1&&c2%y1==0)
               {
                   x1=c2/y1;
                   if(jud(x1,y1)){printf("Yes\n");continue;}
               }
            }
             printf("No\n");
             continue;
        }
        y1=c2-c1-n1*m1+temp;y2=c2-c1-n1*m1-temp;//y1,y2
        if(y1>=1&&y1<=M&&y1>=(2*n1)&&y1%(2*n1)==0)
        {
            y1=y1/(2*n1);
            if(c1>=y1&&c1%y1==0)
            {
                x1=c1/y1;
               if(jud(x1,y1)) {printf("Yes\n");continue;}
            }
        }
        if(y2>=1&&y2<=M&&y2>=(2*n1)&&y2%(2*n1)==0)
        {
            y2=y2/(2*n1);
            if(c1>=y2&&c1%y2==0)
            {
                x2=c2/y2;
                if(jud(x2,y2)){printf("Yes\n");continue;}
            }
        }
        printf("No\n");
   }
    return 0;
}
/*暴力枚举sqrt级ac*/
#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000;
struct Node
{
  int x,y,v;
}a[N*N+100];
int jud(int p)
{
             int flag;
             for(int i=1;i*i<=a[0].v;i++)
             {
                 if(a[0].v%i==0)
                 {
                     if(a[0].v/i>=a[0].x&&i>=a[0].y)
                     {
                         flag=0;
                         for(int k=1;k<p;k++)
                         {
                             if((a[k].x-a[0].x+a[0].v/i)*(a[k].y-a[0].y+i)!=a[k].v){flag=1;break;}
                         }
                         if(flag==0){return 1;}
                     }
                     if(a[0].v/i>=a[0].y&&i>=a[0].x)
                     {
                         flag=0;
                         for(int k=1;k<p;k++)
                         {
                             if((a[k].x-a[0].x+i)*(a[k].y-a[0].y+a[0].v/i)!=a[k].v){flag=1;break;}
                         }
                         if(flag==0){return 1;}
                     }
                 }
             }
             return 0;
}
int main()
{
    char str[100];
    int t,kcase=1;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,p=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
         {
            scanf("%s",str);
            if(strlen(str)==1&&str[0]=='?') continue;
            int num=0,len=strlen(str);
            for(int k=0;k<len;k++)
                num=num*10+str[k]-'0';
            a[p].x=i;a[p].y=j;a[p++].v=num;
         }
         printf("Case #%d: ",kcase++);
         if(p==0){printf("Yes\n");}
         else if(p==1)
         {
             int flag=0;
             for(int i=1;i*i<=a[0].v;i++)
             {
                 if(a[0].v%i==0)
                 {
                     if(a[0].v/i>=a[0].x&&i>=a[0].y){flag=1;break;}
                     if(a[0].v/i>=a[0].y&&i>=a[0].x){flag=1;break;}
                 }
             }
             if(flag) {printf("Yes\n");}
             else printf("No\n");
         }
         else
         {
             if(jud(p)) printf("Yes\n");
             else printf("No\n");
         }
    }
    return 0;
}
点击打开链接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:这段引用是一段C++代码,用于处理一个01序列的查询。代码中使用了前缀和和后缀和的思想,通过计算每个位置之前1的个数和之后1的个数,来处理查询区间内的操作。具体的实现细节可以参考代码注释。\[1\] 引用\[2\]:在处理多组询问时,为了不改变非连续1的计数,代码将区间分成两段处理。左半段都是1的情况单独处理,后半段第一个位置为0,可以通过前缀和相减来计算。这样可以保证在处理查询时不会影响到非连续1的计数。\[2\] 引用\[3\]:这段引用是对一个二进制循环序列的定义和问题描述。一个好的二进制循环序列是指通过一系列操作可以使其变为空序列。而一个二进制循环序列的美丽度被定义为使其变为好序列所需的最小修改次数。每次修改可以翻转序列中的任意一个元素,即0变为1,1变为0。给定一个长度为n的二进制字符串a和q个查询,每个查询给出两个整数li和ri,需要回答f(aliria\[li..ri\]),其中我们将子字符串aliria\[li..ri\]视为一个循环序列。\[3\] 问题: 请问这段代码的作用是什么? 回答: 这段代码的作用是处理一个01序列的查询。通过计算每个位置之前1的个数和之后1的个数,来处理查询区间内的操作。在处理多组询问时,为了不改变非连续1的计数,代码将区间分成两段处理,保证在处理查询时不会影响到非连续1的计数。最终输出每个查询区间的结果。\[1\]\[2\] #### 引用[.reference_title] - *1* *2* [ICPC22网络赛(1) - A 01 Sequence(前缀和,思维)](https://blog.csdn.net/Mr_dimple/article/details/126983251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [The 2022 ICPC Asia Regionals Online Contest - A 01 Sequence](https://blog.csdn.net/qq_35339563/article/details/126959132)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值