题解

这题显然是\(总方案数不可行方案数总方案数-不可行方案数\)(直接算是无规则的)。总方案数是\(n^2m^2\),于是问题就在于不可行的方案数。

若queen落在一个点上,则横竖是十分好求的(\(n+m\)),如果能求出斜的两条就完美了。

我们发现,这种方法Q的位置会加三次,于是我们可以在最后统一减\(3nm\)。

然后比较困难的是求斜的边。

假定我们求从左上到右下线的总长度。钦定\(n\le m\)。于是就得到这样一张图:

绿色区域的点和竖线是等效的,主要是白色区域。

对于每一条斜线,我们发现第\(i\)线上的点的个数是\(i\),于是我们就可以很容易地得出不可行方案数的总和为,\(\sum_{i=1}^n i^2\)有于有4块(反着还有两块),故要乘4。

于是就是要快速求出\(\sum_{i=1}^n i^2\)。。\(\sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6}\)由于我太菜了,只会归纳法,本想看一下如何现场手推(想看如何现场推的可以点这里)。

于是最后就是高精的问题了,可以不压位。

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring> using namespace std; const int width = 4;
const int mod = 1e4; typedef long long LL; struct HugeInt
{
int a[50];
int len; inline void clear()
{
memset(a, 0, sizeof(a));
len = 0;
}
}; HugeInt operator + (HugeInt a, HugeInt b)
{
HugeInt c;
c.clear();
int maxlen = max(a.len, b.len);
for(int i = 0; i < maxlen; ++i)
{
c.a[i] += a.a[i]+b.a[i];
c.a[i+1] += c.a[i]/mod;
c.a[i] %= mod;
}
c.len = maxlen;
while(c.a[c.len])
c.len++;
return c;
} HugeInt operator - (HugeInt a, HugeInt b)
{
HugeInt c;
c.clear();
c.len = a.len;
for(int i = 0; i < c.len; ++i)
{
c.a[i] += a.a[i]-b.a[i];
if(c.a[i]<0)
{
a.a[i+1]--;
c.a[i] += mod;
}
}
while(!c.a[c.len-1] && c.len>=1)
c.len--;
return c;
} HugeInt operator * (HugeInt a, HugeInt b)
{
HugeInt c;
c.clear();
for(int i = 0; i < a.len; ++i)
for(int j = 0; j < b.len; ++j)
c.a[i+j] += a.a[i] * b.a[j];
c.len = a.len + b.len - 1;
for(int i = 0; i < c.len; ++i)
{
c.a[i+1] += c.a[i]/mod;
c.a[i] %= mod;
}
while(c.a[c.len])
c.len++;
return c;
} bool operator < (HugeInt a, HugeInt b)
{
if(a.len != b.len)
return a.len < b.len;
else
{
for(int i = a.len-1; i >= 0; --i)
{
if(a.a[i] != b.a[i])
return a.a[i] < b.a[i];
}
}
return false;
} HugeInt give(long long a)
{
HugeInt re;
re.clear();
while(a)
{
re.a[re.len++] = a%mod;
a /= mod;
}
return re;
} HugeInt operator + (HugeInt a, LL b)
{
return a + give(b);
} HugeInt operator + (LL a, HugeInt b)
{
return b + a;
} HugeInt operator * (HugeInt a, LL b)
{
return a * give(b);
} HugeInt operator * (LL a, HugeInt b)
{
return b * a;
} HugeInt operator - (HugeInt a, LL b)
{
return a - give(b);
} HugeInt operator / (HugeInt a,LL b)
{
HugeInt ans;
ans.clear();
ans=a;
LL my=0;
for(int i=ans.len-1; i>=0; i--)
{
ans.a[i]+=my;
my=ans.a[i]%b*mod;
ans.a[i]/=b;
}
while(!ans.a[ans.len-1])
ans.len--;
return ans;
} void print(HugeInt a)
{
printf("%d", a.a[a.len-1]);
for(int i = a.len-2; i>=0; --i)
printf("%04d", a.a[i]);
} void solve(LL n, LL m)
{
if(m < n)
swap(n, m);
HugeInt nn = give(n);
HugeInt mm = give(m);
print(nn*nn*mm*mm-(nn*(nn+1)*(nn*2+1)/3*2+nn*nn*2*(mm-nn-1)+(nn+mm)*nn*mm-3*nn*mm));
puts("");
} int main()
{
freopen("queen.in", "r", stdin);
freopen("queen.out", "w", stdout);
int nmn;
long long a, b;
scanf("%d", &nmn);
while(nmn--)
{
scanf("%lld%lld", &a, &b);
solve(a, b);
}
return 0;
}

最新文章

  1. C# 获取当前月第一天和最后一天 计算两个日期差多少天
  2. VS2013 带命令行参数的调试问题 解决方案
  3. javascript的基本语法、数据结构
  4. mysql概要(四)order by,group 的特点,子查询
  5. c#中操作word文档-一、模板方式写入
  6. Asp.Net 自定义控件实现图片的上传,浏览,删除功能
  7. js字符串常用判断方法
  8. 【转】Linux I2C设备驱动编写(三)-实例分析AM3359
  9. Linux下自动备份MySQL
  10. 上海2017QCon个人分享总结
  11. 音乐出身的妹纸,零基础学习JAVA靠谱么
  12. __slots__,__doc__,__del__,__call__,__iter__,__next__迭代器协议(三十六)
  13. 微信公开课厦门站 时尚行业专场PPT
  14. bzoj 4585 烟火表演 - 动态规划 - 可并堆
  15. YII2.0使用ActiveForm表单(转)
  16. Ionic构建打包apk出现的问题集合
  17. appserv - 最简单的绑定路径
  18. ubuntu 12.04下gedit查看txt中文乱码解决办法
  19. Android------底部导航栏BottomNavigationBar
  20. 六:ZooKeeper的java客户端api的使用

热门文章

  1. c# 大白话告诉你Thread的Sleep和Join的区别
  2. [教程]K8Cscan调用外部程序(Win/Linux批量上控/执行多条命令/保存结果)
  3. [转帖]程序员:我终于知道post和get的区别
  4. 更新Linux内核
  5. thymeleaf是用于编写html模版的编程语言(工具语言)
  6. 如何通过 IntelliJ IDEA 来提升 Java8 Stream 的编码效率
  7. 深入理解TCP/IP传输层
  8. .net list转树状结构
  9. 《JavaEE开发的颠覆者——Spring Boot实战》是一本好书
  10. Java深入学习(5):锁