列表

详情


NC19153. 无限手套

描述

小w得到了传说中的无限手套,只要装上宝石就能发挥出强大的力量,现在小w拥有m种宝石,每种宝石都拥有足够多的数量。第i种宝石具有属性ai和bi,如果无限手套上第i种宝石有xi个,那么手套的力量就是

现在小w想知道如果手套上能安装n个宝石,那么对于所有可能的安装宝石的方案,手套最终所能得到的力量之和。

输入描述

第一行一个正整数m表示宝石的种类(1<=m<=1000)
接下来M行,每行两个正整数ai, bi(0<=ai, bi<=10^9)
接下来一行正整数q,共有q次询问(1<=q<=1000)
接下来q行每行一个正整数n询问如果无限手套可以安装n个宝石则力量之和是多少。(1<=n<=10000)

输出描述

一共q行,每行一个正整数表示答案。
答案对998244353取模。

示例1

输入:

2
2 1
1 0
2
3
4

输出:

74
193

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 205ms, 内存消耗: 612K, 提交时间: 2019-07-30 19:43:41

#include <bits/stdc++.h>
using namespace std;
const int N=10005;
const int MD=998244353;
int f[2][N];
void add(int &x,int y)
{
	x+=y;
	if(x>MD) x-=MD;
}
int main()
{
	int m,q,x,s=1,cnt=0;
	scanf("%d",&m);
	f[0][0]=1;
	for(int i=0,a,b;i<m;i++)
	{
		scanf("%d%d",&a,&b);
		for(int j=0;j<s+2;j++) f[cnt^1][j]=0;
		for(int j=0;j<s;j++)
		{
			add(f[cnt^1][j+2],(1LL*f[cnt][j]*(a-b+1)%MD+MD)%MD);
			add(f[cnt^1][j+1],(1LL*f[cnt][j]*(a+b-2)%MD+MD)%MD);
			add(f[cnt^1][j],f[cnt][j]);
		}
		s+=2;
		cnt^=1;
	}
	int t=3*m;
	while(t--)
	{
		for(int j=1;j<=10000;j++)
			add(f[cnt][j],f[cnt][j-1]);
	}
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d",&x);
		printf("%d\n",f[cnt][x]);
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 175ms, 内存消耗: 612K, 提交时间: 2019-10-08 10:51:39

#include<cstdio>
using namespace std;
const long long mod=998244353;
int m,a,b,q,x;
long long f[10005];
int main()
{
	scanf("%d",&m);
	f[0]=1;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		long long A=(0LL+a-b+1+mod)%mod,B=(0LL+a+b-2+mod)%mod;
		for(int i=10000;i>=2;i--)
			f[i]=(f[i]+f[i-1]*B+f[i-2]*A)%mod;
		f[1]=(f[1]+f[0]*B)%mod;
		for(int k=1;k<=3;k++)
		for(int i=1;i<=10000;i++)
			f[i]=(f[i]+f[i-1])%mod; 
	}
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d",&x);
		printf("%lld\n",f[x]);
	}
}

上一题