ZROJ 446 数独 【思维】【搜索】

题意:
T组数据,每组数据有一个9*9的数独,数独初始全为 0/1, 0表示无限制,1表示该位置不能放1,问合法数独方案数(模998244353)
样例:
1
101101010
010000100
100100100
001001000
111011100
100100100
111010100
010101011
101101010
ans:915672442

吐槽:
这题我花了一个小时剪枝跑了5h没跑出来(捂脸

题解:
有一个很厉害的公式:
a n s = ans= ans=数独总合法数*当前1可填的合法方案数/1可填的总合法方案
数独总合法数=样例中1的总填法/样例输出=719935075(取模后)
同理可得1可填的合法方案数=46656,求出逆元就ok了
所以只需要暴搜出“当前1可填的合法方案数”就行了。
第一次见到用样例推结论的题233333
代码很短题目很难。

// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)

using namespace std;

typedef long long LL;

const int inf = 1 << 30;
const int n=9;
const int i_love_zlf=804434861;
const int maxn=15;

int T;
char s[maxn+5][maxn+5];
int a[maxn][maxn];
int cnt=0;
int c[maxn],su[maxn+5][maxn+5];

void dfs(int now){
	if(now==n+1){++cnt;return ;}
	for(int i=1;i<=n;i++){
		if(!c[i]&&su[(now-1)/3][(i-1)/3]==0&&!a[now][i]){
			c[i]=su[(now-1)/3][(i-1)/3]=1;
			dfs(now+1);
			c[i]=su[(now-1)/3][(i-1)/3]=0;
		}
	}	
}

int main(){
	scanf("%d",&T);
	while(T--){
		for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)a[i][j]=s[i][j]-'0';
		cnt=0;
		dfs(1);
		printf("%d\n",1ll*i_love_zlf*cnt%998244353);
	}
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值