[SDOI2010]代码拍卖会 C++题解

本文介绍了SDOI2010比赛中的代码拍卖会问题,探讨了符合条件的数的特性,如可拆分为1的序列,并分析了1的序列模p的循环规律。通过预处理计算模p为r的1序列数量,利用动态规划(dp)求解方案数,详细阐述了问题解决思路和代码实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:[SDOI2010]代码拍卖会 - 洛谷

需要注意到两个东西
**
1.符合条件的数可以拆成一堆11...1111...11相加的形式,比如:1145=1111+11+11+11+11145=1111+11+11+11+1
2.1,11,111,1111,...1,11,111,1111,...模pp会出现循环,循环节长度不超过pp
**
还有就是11...1111...11最多为99个,然后就可以dpdp了。
首先需要统计长度为1−n1−n的全11串中有多少个模pp为rr,记为cnt[r]cnt[r],这个可以O(p)O(p)的预处理出来
接着设f[k][i][j]f[k][i][j]表示在cnt[1]−cnt[i]cnt[1]−cnt[i]中已经选了kk个,且它们的和模pp为jj的方案数。为什么是88而不是99呢?因为我们至少要选一个长度为nn的全11串,为了方便,我们在dpdp之前就把它选出来,相当于占用了99个中的11个
还有就是那个组合是可重组合
细节看代码吧:

#include <bits/stdc++.h>

using namespace std;

#define $SHOW(x) cout << #x" = " << x << endl

#define ll long long
#define MOD 999911659
#define MAXN 500

ll n, P, all, cnt[MAXN + 5], inv[10]; // all代表长度为n的全1串模p的值
int st, len, pos[MAXN + 5], f[10][MAXN + 5][MAXN + 5];

void add(int &x, int y) {
    x = (x + y) % MOD;
    if(x < 0) x += MOD;
}

int 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值