原题链接
这道题真的给我恶心坏了……
本来是以为自己的思路出了问题,极限答案多出来几千多
后来按其他人的思路做了一遍,还是莫名其妙的多几十
找了半天才发现是pow函数没做强制转换的锅…
pow() 函数用来求 x 的 y 次方的值。
头文件:math.h
语法/原型:
double pow(double x,double y);
参数说明:
x:双精度数。
y:双精度数。
返回值:x 的 y 次方的值。
大概是因为极限情况下数值过大把double的整数部分撑炸了,得强制类型转换才成。
我的思路
按数枚举,计算这个数右方和下方两个方向相同颜色方格的数量,一个方向加上2n-1个答案(相当于取这个方格之后所有同颜色方格做组合,Cn1+Cn2+…+Cnn=2n-1),最后加上只有方格自己的m*n。
复杂度O(n3),在这道题的数据范围内是可接受的。
#include<bits/stdc++.h>
using namespace std;
#define N 55
typedef long long LL;
int main()
{
//一直没过改的属实是杞人忧天了,除了ans都不用LL的
LL n;
LL m;
LL a[N][N];
LL ans=0;
LL i;
LL j;
cin>>n>>m;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
cin>>a[i][j];
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
LL flag=0;//计算后面同颜色方块的数量
LL k=j+1;//遍历用的指针
for(;k<m;k++)//遍历
if(a[i][j]==a[i][k]) flag++;
ans+=(LL)pow(2,flag)-1;//滥用类型害死人
k=i+1;
flag=0;
for(;k<n;k++)
if(a[i][j]==a[k][j]) flag++;
ans+=(LL)pow(2,flag)-1;
}
}
ans+=m*n; //补本身
cout<<ans;
return 0;
}
诸题解的思路,按行列遍历每行/列方块的情况,答案加上2黑块-1+2百块-1,最后减去重复的子集m*n。
复杂度O(n2),比我的思路快很多 快一丢丢。
好像还看到有神犇在输入的时候就用前缀和来存的,tql
#include<bits/stdc++.h>
using namespace std;
#define N 55
typedef long long LL;
int main()
{
int n;//行
int m;//列
int a[N][N];
LL ans=0;
int i;
int j;
cin>>n>>m;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
cin>>a[i][j];
}
//按行遍历
for(i=0;i<n;i++)//行下标
{
int x=0;
for(j=0;j<m;j++)//列下标
if(a[i][j]==1) x++;
ans+=(LL)pow(2,x)+(LL)pow(2,m-x)-2;//问题就出在这个(LL)上......
}
//按列遍历
for(j=0;j<m;j++)
{
int x=0;
for(i=0;i<n;i++)
if(a[i][j]==1) x++;
ans+=(LL)pow(2,x)+(LL)pow(2,n-x)-2;
}
ans-=m*n;//去重
cout<<ans;
return 0;
}