Character Encoding
题面
In computer science, a character is a letter, a digit, a punctuation mark or some other similar symbol. Since computers can only process numbers, number codes are used to represent characters, which is known as character encoding. A character encoding system establishes a bijection between the elements of an alphabet of a certain size \(n\) and integers from \(0\) to \(n-1\). Some well known character encoding systems include American Standard Code for Information Interchange (ASCII), which has an alphabet size 128, and the extended ASCII, which has an alphabet size 256.
For example, in ASCII encoding system, the word \(\texttt{wdy}\) is encoded as [119, 100, 121], while \(\texttt{jsw}\) is encoded as [106, 115, 119]. It can be noticed that both \(119+100+121=340\) and \(106+115+119=340\), thus the sum of the encoded numbers of the two words are equal. In fact, there are in all 903 such words of length 3 in an encoding system of alphabet size 128 (in this example, ASCII). The problem is as follows: given an encoding system of alphabet size \(n\) where each character is encoded as a number between 0 and \(n-1\) inclusive, how many different words of length \(m\) are there, such that the sum of the encoded numbers of all characters is equal to \(k\)?
Since the answer may be large, you only need to output it modulo 998244353.
发现其他题解要么很模糊,要么说了一大堆废话,写篇题解梳理一下这道题的思路。
题意
给你三个数 \(n,m,k\),求出从 \([0,n-1]\) 中选择 \(m\) 个数,使其和为 \(k\) 的方案数,答案对 998244353 取模
思路
我们可以想象成有 \(k\) 个小球,放进 \(m\) 个盒子里(每放一个数就相当于加 \(1\))且允许有空盒子(因为可以有数为 \(0\))。
我们可以先把每个盒子都放一个球,相当于有 \(k+m\) 个球,\(m\) 个盒子,用插板法很容易得到答案为 \(C_{k+m}^m\)。
但是这道题目有数 \(<n\) 的限制,所以我们要将所有序列中数 \(\ge n\) 全部舍去,最多有 \(\lfloor\cfrac{k}{n}\rfloor\) 个 \(n\),注意到 \(x\) 个 \(n\) 是被 \(x+1\) 个 \(n\) 包含的,所以我们需要用容斥原理。
答案即为 \(\sum\limits_{i=0}^{\lfloor\frac{k}{n}\rfloor} (-1)^iC_{k+m-i\times n}^{m-1}C_m^i\)
一些细节
- 有很多 OIer 会对最后的 \(C_i^m\) 产生疑问:由于我们相当于是在计算 \(m\) 个数中 \(\ge n\) 的个数,所以是在 \(m\) 个数中选 \(i\) 个 \(\ge n\) 的数,要用 \(C_i^m\)。
- 记得取模,由于计算 \(C\) 需要除法,所以要用逆元,用费马小定理解决即可。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> P;
typedef __int128 int128;
#define IOS ios::sync_with_stdio(0);
#define rep(i,x,y,z) for(int i = x;i <= y;i+=z)
#define per(i,y,x,z) for(int i = y;i >= x;i-=z)
#define frin(x) freopen(x,"r",stdin);
#define frout(x) freopen(x,"w",stdout);
const int N = 1e6 + 5;
const int M = 2e3 + 5;
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int dx[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int dy[] = {0, 0, -1, 1, 1, -1, -1, 1};
inline ll read();
inline void solve();
inline void print(ll x);
inline ll gcd(ll x,ll y);
inline ll lcm(ll x,ll y);
inline ll fastpow(ll x,ll y,ll p);
struct Big {
int len, s[810];
Big() {
memset(s, 0, sizeof(s));
len = 1;
}
Big(int val) {
*this = val;
}
Big(const char *val) {
*this = val;
}
Big operator = (const int &val) {
char s[810];
sprintf(s, "%d", val);
*this = s;
return *this;
}
Big operator = (const char *val) {
len = strlen(val);
while (len > 1 && val[0] == '0') ++val, len--;
for ( int i = 0; i < len; ++i) s[i] = val[len - i - 1] - '0';
return *this;
}
inline void deal() {
while (len > 1 && !s[len - 1]) len--;
}
Big operator + (const Big &a) const {
Big res;
res.len = 0;
int top = max(len, a.len), add = 0;
for ( int i = 0; add || i < top; ++i) {
int now = add;
if (i < len) now += s[i];
if (i < a.len) now += a.s[i];
res.s[res.len++] = now % 10;
add = now / 10;
}
return res;
}
Big operator - (const Big &a) const {
Big res;
res.len = 0;
int del = 0;
for ( int i = 0; i < len; ++i) {
int now = s[i] - del;
if (i < a.len) now -= a.s[i];
if (now >= 0) del = 0;
else del = 1, now += 10;
res.s[res.len++] = now;
}
res.deal();
return res;
}
Big operator * (const Big &a) const {
Big res;
res.len = len + a.len;
for ( int i = 0; i < len; ++i)
for ( int j = 0; j < a.len; ++j)
res.s[i + j] += s[i] * a.s[j];
for ( int i = 0; i < res.len; ++i)
res.s[i + 1] += res.s[i] / 10, res.s[i] %= 10;
res.deal();
return res;
}
Big operator / (const Big &a) const {
Big res, cur = 0;
res.len = len;
for ( int i = len - 1; ~i; --i) {
cur = cur * 10, cur.s[0] = s[i];
while (cur >= a)
cur -= a, res.s[i]++;
}
res.deal();
return res;
}
Big operator % (const Big &a) const {
Big res = *this / a;
return *this - res * a;
}
Big operator += (const Big &a) {
*this = *this + a;
return *this;
}
Big operator -= (const Big &a) {
*this = *this - a;
return *this;
}
Big operator *= (const Big &a) {
*this = *this * a;
return *this;
}
Big operator /= (const Big &a) {
*this = *this / a;
return *this;
}
Big operator %= (const Big &a) {
*this = *this % a;
return *this;
}
bool operator < (const Big &a) const {
if (len != a.len) return len < a.len;
for ( int i = len - 1; ~i; i--)
if (s[i] != a.s[i]) return s[i] < a.s[i];
return false;
}
bool operator > (const Big &a) const {
return a < *this;
}
bool operator <= (const Big &a) const {
return !(*this > a);
}
bool operator >= (const Big &a) const {
return !(*this < a);
}
bool operator == (const Big &a) const {
return !(*this > a || *this < a);
}
bool operator != (const Big &a) const {
return *this > a || *this < a;
}
Big Sqrt(const Big &x) {
int a[510], top = 0;
for ( int i = 0; i < x.len; i += 2) {
if (i == x.len - 1) a[top++] = x.s[i];
else a[top++] = x.s[i] + x.s[i + 1] * 10;
}
Big res = (int)sqrt((double)a[top - 1]);
int dat = (int)sqrt((double)a[top - 1]);
Big pre = a[top - 1] - dat * dat, val;
for ( int i = top - 2; ~i; --i) {
pre = pre * 100 + a[i], val = res * 20;
for ( int j = 9; ~j; --j) {
Big now = (dat + j) * j;
if (now > pre) continue;
res = res * 10 + j;
pre -= now;
break;
}
}
return res;
}
void print(const Big &a) {
for ( int i = a.len - 1; ~i; --i)
printf("%d", a.s[i]);
puts("");
}
int read() {
int a = 0, b = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
b = (ch == '-') ? -1 : 1, ch = getchar();
while (ch >= '0' && ch <= '9')
a = (a << 3) + (a << 1) + (ch ^ 48), ch = getchar();
return a * b;
}
};
ll p = 998244353;
ll fac[N];
int main()
{
IOS;
//frin("");frout("");
int T = 1;
fac[0] = 1;
rep(i,1,N - 1,1) fac[i] = fac[i - 1] * i % p;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
inline ll read()
{
ll s = 0, w = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
s = s * 10 + c - '0';
c = getchar();
}
return s * w;
}
inline void print(ll x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x >= 10)
{
print(x / 10);
}
putchar(x % 10 + '0');
return;
}
inline ll fastpow(ll x, ll y, ll p)
{
ll ans = 1;
while (y)
{
if (y % 2)
{
ans = (ans * x) % p;
}
x = (x * x) % p;
y >>= 1;
}
return ans;
}
inline ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
inline ll lcm(ll a, ll b)
{
return a * b / gcd(a, b);
}
inline ll C(ll n,ll r) {
if(r > n) return 0;
return fac[n] * fastpow(fac[r],p - 2,p) % p * fastpow(fac[n - r],p - 2,p) % p;
}
inline void solve()
{
ll n,m,k;
cin >> n >> m >> k;
if(n * m - m < k) {
cout << 0 << endl;
return ;
}
ll ans = 0;
rep(i,0,k / n,1) {
ll tmp = C(k - i * n + m - 1,m - 1) * C(m,i) % p;
if(i & 1) ans = (ans - tmp + p) % p;
else ans = (ans + tmp) % p;
}
cout << ans << endl;
}
感谢观看!

浙公网安备 33010602011771号