很简单但是给我启发很大的题目。对于怎么确定要填的数字所在小方块位置使用打表的方法,这一点一开始没能想到。
#include <bits/stdc++.h>
using namespace std;
int cnt;
int col[10][10],line[10][10],squr[10][10];
int arr[10][10];
int num[10][10] = {
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9}
};
struct Node{
int x,y;
}a[100];
bool check(int x,int y,int z){
return line[x][z] || col[y][z] || squr[num[x][y]][z];
}
void dfs(int pos){
if (pos>cnt){
for (int i=1;i<=9;i++){
for (int j=1;j<=9;j++)
printf("%d ",arr[i][j]);
printf("\n");
}
return;
}
for (int i=1;i<=9;i++){
int xx = a[pos].x,yy = a[pos].y;
if (check(xx,yy,i)) continue;
arr[xx][yy] = i;
line[xx][i] = 1;
col[yy][i] = 1;
squr[num[xx][yy]][i] = 1;
dfs(pos+1);
arr[xx][yy] = 0;
line[xx][i] = 0;
col[yy][i] = 0;
squr[num[xx][yy]][i] = 0;
}
}
signed main(){
for (int i=1;i<=9;i++){
for (int j=1;j<=9;j++){
scanf("%d",&arr[i][j]);
if (arr[i][j]==0){
cnt++;
a[cnt].x = i;
a[cnt].y = j;
}
else {
line[i][arr[i][j]] = 1;
col[j][arr[i][j]] = 1;
squr[num[i][j]][arr[i][j]] = 1;
}
}
}
dfs(1);
}
思路很快就想到,就是枚举幸运数字然后一个个计数。
但是在某个点上调了很久,
//错误代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int l,r,ans;
int mini = 1e18;
void dfs(int num,bool ok){
if (num>=r){
mini = min(num,mini);
return;
}
if (num>=l&&ok){
ans += (num-l+1ll) * num;
l = num + 1ll;//错误点在这里
}
dfs(num*10ll+4ll,1);
dfs(num*10ll+7ll,1);
}
signed main(){
scanf("%lld%lld",&l,&r);
dfs(0,0);
//cout<<l<<endl;
ans += (r-l+1ll) * mini;
printf("%lld",ans);
}
说一下错误原因:枚举的时候,是按前序遍历枚举的,即先枚举到的数不是最小数,但我默认了先枚举到的就是最小数,根据这个数调整左指针。
正确思路:依旧是全部枚举,但要将这些数都放在容器里,排序后逐一二分搜索。
//正确思路
#include <bits/stdc++.h>
#define int long long
using namespace std;
int l,r,ans;
int maxi = 5e9;
vector<int>v;
void dfs(int num,bool ok){
if (num>=maxi){
return;
}
if (ok){
v.push_back(num);
}
dfs(num*10ll+4ll,1);
dfs(num*10ll+7ll,1);
}
signed main(){
scanf("%lld%lld",&l,&r);
dfs(0,0);
sort(v.begin(),v.end());
for (auto it:v){
if (l>r) break;
int pos = upper_bound(v.begin(),v.end(),l) - v.begin();
if (pos>0&&v[pos-1]>=l) pos--;
ans += (min(v[pos],r)-l+1) * v[pos];//这边需要注意
l = v[pos] + 1;//调整左指针
}
printf("%lld",ans);
}