acw17周周赛 T2 方格集数量

本文介绍了一种在计算中遇到的pow函数精度问题,并通过强制类型转换解决了该问题。同时给出了两种不同思路的代码实现,一种是通过枚举计算每个方格同色数量,另一种则是按行列遍历统计黑白方块数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接

这道题真的给我恶心坏了……
本来是以为自己的思路出了问题,极限答案多出来几千多
后来按其他人的思路做了一遍,还是莫名其妙的多几十
找了半天才发现是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值