2021年ICPC江西省赛——部分个人题解
A
https://codeforces.com/gym/406715/problem/A
题意:
给定一个n * m的01矩阵,求从(1,1)到(n,m)的所有路径中,至少有p次0和q次1的路线数。
思路:
容易看到,如果单纯的dfs(),绝对超时,所以考虑是不是与dp有关;
首先考虑到可以用f[i][j][k][l]表示从起点开始到点(i, j),并且走过了k个0,l个1的路径数;
对于它的第一步优化:在01矩阵中,从(1,1)到任意一点的任意一个路线,当经过0的数量确定时,经过1的数量即为i j-1-k,所以这个dp首先可以优化成f[i][j][k]表示走到第i行第j列时,经过k次0方案数。
由此可以推出其状态转移方程:
1.当a[ i ][ j ] == 0时,f[ i ][ j ][ k ] = f[ i - 1 ][ j ][ k - 1 ] f[ i ][ j - 1 ][ k - 1 ];
2.当a[ i ][ j ] == 1时,f[ i ][ j ][ k ] = f[ i - 1 ][ j ][ k ] f[ i ][ j - 1 ][ k ];
但是当n=m=500,k=1000时,三维数组需要大量的空间,所以我们需要在进行一轮压缩;
注意到,其实转移只可能是从当前点所在行的上一行,和当前行两行转移,那么可以把i改成2,就两种状态,初始状态,当第一个点为1,那么,dp[1][1][0] = 1, 第一个1也可以是0,随便假设,第二个就是列数,第三个就是走过0个0,反之dp[1][1][1] = 0;
类似于背包问题中的二维压一维;
最后AC代码如下:
-
-
using namespace std;
-
const int N = 510, mod = 998244353;
-
typedef long long ll;
-
-
int n, m, p, q;
-
int a[N][N];
-
ll f[N][N*3];//注意N * 3;
-
-
int main()
-
{
-
cin >> n >> m >> p >> q;
-
-
for(int i = 1; i <= n; i )
-
for(int j = 1; j <= m; j )
-
cin >> a[i][j];
-
-
if(!a[1][1]) f[1][1] = 1;
-
else
-
f[1][0] = 1;
-
-
for(int i = 1; i <= n; i )
-
{
-
for(int j = 1; j <= m; j )
-
{
-
for(int k = i j - 1; k >= 0; k -- )
-
{
-
if(i == 1 && j == 1) continue;
-
if(a[i][j]) f[j][k] = (f[j][k]%mod f[j - 1][k] % mod) % mod;
-
else
-
{
-
if(k) f[j][k] = (f[j][k - 1]%mod f[j - 1][k - 1]%mod) % mod;
-
}
-
}
-
if(!a[i][j]) f[j][0] = 0;
-
}
-
}
-
-
ll res = 0;
-
for(int i = 1; i <= m n - 1; i )
-
{
-
if(i >= p && m n - 1 - i >= q)
-
res = (res f[m][i]) % mod;
-
}
-
-
cout << res << "\n";
-
return 0;
-
}
B
https://codeforces.com/gym/406715/problem/B
题意:给定一个x一个y,将x/y化简成如下图式子:
如:
思路:可以模拟:对第一个样例分析——:105 / 38,a[ 0 ]显然是 x / y ,右式a[ 1 ]为 y / (x % y);。
AC代码如下:
-
-
using namespace std;
-
const int N=1e5 10;
-
int ans[N];
-
void solve()
-
{
-
int a,b;
-
int cnt=0;
-
cin>>a>>b;
-
while(1)
-
{
-
ans[cnt ]=a/b;
-
int temp;
-
temp=b;
-
b=a%b;
-
a=temp;
-
if(a==1)
-
break;
-
}
-
cout<<cnt-1<<" ";
-
for(int i=0;i<cnt;i )
-
cout<<ans[i]<<" ";
-
cout<<endl;
-
}
-
int main()
-
{
-
int t;
-
cin>>t;
-
while(t--)
-
{
-
solve();
-
}
-
return 00;
-
}
K
https://codeforces.com/gym/406715/problem/K
题意:有t组输入,每组输入一个n,一个m,表示有n层,第i层有i*i个房间,每个房间有m个人,求有多少人。
思路:数据小,暴力求和即可
AC代码:
-
-
using namespace std;
-
void solve()
-
{
-
int n,m;
-
cin>>n>>m;
-
long long ans=0;
-
for(int i=1;i<=n;i )
-
{
-
ans =i*i;
-
}
-
ans*=m;
-
cout<<ans<<endl;
-
}
-
int main()
-
{
-
int t;
-
cin>>t;
-
while(t--)
-
solve();
-
return 0;
-
}
L
https://codeforces.com/gym/406715/problem/L
题意:给定n个板子,每个板子是从x1,y1伸展到x2,y2。有雨会从正上方下来,询问有多少长度的坐标轴是淋不到雨的。
思路:显然,坐标y对结果不会产生影响,所以我们先用x1与x2排序,然后只需要维护每个板子的x2为last,然后与下一个板子的x2比较——有两种情况:
1、q[i].x2 <= last
2、q[i].x2 > last
则有:
AC代码:
-
-
using namespace std;
-
const int N=1e6 10;
-
struct node
-
{
-
int x1;
-
int y1;
-
int x2;
-
int y2;
-
}q[N];
-
bool cmp(node n1,node n2)
-
{
-
return n1.x1<n2.x1;
-
}
-
int main()
-
{
-
int n;
-
int a,b,c,d;
-
scanf("%d",&n);
-
for(int i=0;i<n;i )
-
{
-
cin>>a>>b>>c>>d;
-
if(a<c)
-
{
-
q[i].x1=a;
-
q[i].y1=b;
-
q[i].x2=c;
-
q[i].y2=d;
-
}
-
else
-
{
-
q[i].x1=c;
-
q[i].y1=d;
-
q[i].x2=a;
-
q[i].y2=b;
-
}
-
}
-
sort(q,q n,cmp);
-
int last=q[0].x1;
-
long long ans=0;
-
for(int i=0;i<n;i )
-
{
-
if(q[i].x2<=last)
-
continue;
-
ans =q[i].x2-q[i].x1;
-
int add=last-q[i].x1;
-
if(add>0)
-
ans-=add;
-
last=q[i].x2;
-
}
-
cout<<ans;
-
}
-
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhffkggj
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24