5.29模拟赛
第一题:sum
题目描述:
求有多少N 位十进制数是P 的倍数且每位之和小于等于M,允许前导0,答案对998244353 取模。
输入格式:
一行三个整数N,P,MM。MM 的含义见输出格式。
输出格式:
一行输出MM+1 个整数,第i个(从0 开始)表示M=i 时的答案
样例输入:
2 3 3
样例输出:
1 1 1 5
数据规模与约定:
对于测试点1:1<=N<=1000.1<=P<=50.1<=MM<=5
对于测试点2,3:1<=N<=10^9.1<=P<=50.1<=MM<=5
对于测试点4,5,6:1<=N<=10^9.1<=P<=50.1<=MM<=50
对于测试点7,8,9,10:1<=N<=10^9.1<=P<=16.1<=MM<=1000
题解:
10分:
f[i][j][k]
表示一个i位的数字,mod P为j,各位的和为k的方案数。
枚举在最后加上一个数字x,去更新
f[i+1][(j×10+x)modP][k+x]
30分:
矩阵快速幂优化dp转移。
60分:
倍增优化dp转移。
设
f[i][j][k]
表示
2i
位,mod P为j,各位的和为k的方案数。
我们可以用两个长度为
2i
的拼成一个长度为
2i+1
的。
具体来说,就是:
怎么得到答案:长度为n的呢?
仿照上面的原理,合并两个长度为长度为
求出f来之后选择一些组合一下得到答案。
选那些f呢?就像快速幂一样,用n的二进制是1的位对应的f统计答案。
(其实和上面的原理一样,只不过这里合并的两段的长度不相等)
设g[2][j][k]表示答案,假如n的二进制第i位是1,则:
答案是: g[now][0][m] .
100分:
NTT优化倍增。
不会。。。
Code:
//NULL
第二题:set
题目描述:
给出n 个非负整数,将数划分成两个集合,记为1号集合和2 号集合。x1
为1号集合中所有数的异或和,x2 为2 号集合中所有数的异或和。在最大化
x1+x2 的前提下,最小化x1。
输入格式:
第一行包含一个整数n。第二行包含n 个用空格隔开的数字,保证它们都
是不超过10^18 的非负整数。
输出格式:
输出一行一个数,表示最优方案中的x1。
样例输入:
8
1 1 2 2 3 3 4 4
样例输出:
7
数据规模与约定:
对于30%的数据,保证n<=10;
对于60%的数据,保证n<=1000;
对于100%的数据,保证n<=100000。
题解:
30分:
暴力枚举。
60分:
假设ALL是所有数的抑或和,比如ALL=100110……
对于ALL中是1的位,不管怎么分,一定是一个集合这一位是1,另一个这一位是0。
对于ALL中是0的位,两种情况,两个集合的这一位分别是(1,1)或者(0,0),我们当然希望是(1,1)。
为了使x1+x2最大,我们要先考虑第二种是0的位,尽量拆成(1,1);然后再考虑是1的位,尽量让x1这一位是0,x2是1。
等价于 先考虑0的位,尽量让x2是1(此时x1也一定是1);再考虑是1的位,尽量让x2是1(此时x1是0)。
这就很像线性基了,只不过枚举位的顺序是先ALL里是0的从高到低,再1的从高到低。
100分:
不会。。。
Code:
//NULL