2023 Hubei Provincial Collegiate Programming Contest(gym104337)E. Inverse Counting Path
题目大意
构造一个01网格图,1能走0不能走
使得从左上走到右下(只能走右或走下)的方案数恰好为x
n<=30,x<=1e9
题解
类似于进制转换,假设能把x写成,表示第i位一个1代表的值,然后再独立构造求和
构造需要满足的条件:
①可以实现对单个乘以
②可以把求和
要求每一小部分都是独立的,不能有格子碰在一起
先这样构造1的块(数字是这样构造时的路径数),设每3行的右上角的数为p[i]:
1
10
74
549
4177
32568
259272
2100064
17257108
143537134
这样构造:
将画线的部分设为1,这样原始部分的方案不会改变,同时可以实现①和②求和
(设p0=1,p1=10,上图就是
按照这样连线 ,在最后一行连一竖来求和即可
如何求ai:从高到低求,如果x>=当前p[i]就减p[i],a[i]+1(也类似进制转换)
(也可以理解成让ai尽量小,所以一次减的数尽量大,每次减最大的能减的数
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;
int n=30,x,i,j,k,l,id,X,Y;
int ans[31][31];
int f[11]={0,1,10,74,549,4177,32568,259272,2100064,17257108,143537134};
int v[11];
void init()
{
fo(i,1,n)
{
l=(i-1)/3+3;
fo(j,1,l)
ans[i][j]=1;
ans[i][n]=1;
}
}
int main()
{
#ifdef file
freopen("E.in","r",stdin);
#endif
init();
scanf("%d",&x);
fd(id,10,1)
{
while (x>=f[id])
{
x-=f[id];
++v[id];
}
if (v[id])
{
X=id*3-2;
Y=id+2;
fo(j,Y,n) ans[X][j]=1;
fo(j,n-v[id]+1,n) ans[X][j]=ans[X+1][j]=1;
}
}
printf("%d\n",n);
fo(i,1,n)
{
fo(j,1,n)
printf("%d ",ans[i][j]);
printf("\n");
}
fclose(stdin);
fclose(stdout);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2020-05-21 CF549E Sasha Circle