「NOIP模拟赛」数位和乘积(dp,高精)
统计方案数,要么组合数,要么递推(dp)了。
这是有模拟赛历史以来爆炸最狠的一次
- T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0
- T3看错题本来简单模拟又给我搞成0分
- T5差分约束本来很简单但是又被我胡搞炸掉了.....
本题T4,难到爆炸的T2把我困住了.....
先讲讲考试看道题的想法:
思考了一会吗,推出几个结论,然后准备写了,感觉可以短时间A掉,结果被T2困住,一小时只优化掉了一个没啥用的n..(n^5logn的复杂度用爱过题)
然后现在来讲讲正解(也是时候背高精板子了)
首先,很容易想到,对于有0出现的数字,其结果一定是0,从而得出一个结论,对于0的结果就是10^n-9^n(不要让我证明)
然后进一步想到,对于给定k进行质因数分解,然后组合&&排列算方案数(我就是这里走了与dp不同的路)
但是发现这样并不好处理,进一步发现,如果k的质因数有大于10的,那么直接输出0(因为一个数位没法装下两个数)
然后,我在这里就暴毙了。
接下来就是正解了。
有了以上结论,我们能非常不容易地想到dp方程式:
$f[i][j][k][m][l]$表示在前i位中,2,3,5,7分别用了几次;
这个转移是真的令人折服。
for (int i = ; i <= n;i++)
{
for (int j = a2; j >= ;j--)
{
for (int k = a3; k >= ;k--)
{
for (int l = a5; l >= ;l--)
{
for (int m = a7; m >= ;m--)
{
if(j>=)
f[j][k][l][m] = f[j - ][k][l][m] + f[j][k][l][m];//
if(k>=)
f[j][k][l][m] = f[j][k - ][l][m] + f[j][k][l][m];//
if(j>=)
f[j][k][l][m] = f[j - ][k][l][m] + f[j][k][l][m];//
if(l>=)
f[j][k][l][m] = f[j][k][l - ][m] + f[j][k][l][m];//
if(j&&k)
f[j][k][l][m] = f[j - ][k - ][l][m] + f[j][k][l][m];//
if(m>=)
f[j][k][l][m] = f[j][k][l][m - ] + f[j][k][l][m];//
if(j>=)
f[j][k][l][m] = f[j - ][k][l][m] + f[j][k][l][m];//
if(k>=)
f[j][k][l][m] = f[j][k - ][l][m] + f[j][k][l][m];//
}
}
}
}
}
对每一位数进行分解,从而得出的方程,其实也不难想,只是没接触过所以想不到
于是,就可以开心地dp了吗?
不,你想死。
当n<=6的时候,方案数就已经上10万了,那么五十....
嘶~~
没有模数??
只能写高精了。
$$但!是!$$
高精*5维数组,会炸空间的....
所以,还要像01背包那样滚掉一维,所以就出现了上述的4维方程式。
于是,代码(这个高精的缺点就在:它太长了!!!!):
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
#define re register
#define max(x,y) ((x)>(y)?(x):(y))
struct node
{
int len,s[];
node(){memset(s,,sizeof(s)); len=;}
node(int val) {*this=val;}
node(const char *val) {*this=val;}
node operator = (const int &val)
{
re char s[];
sprintf(s,"%d",val);
*this=s;return *this;
}
node operator = (const char *val)
{
len=strlen(val);
while(len>&&val[]=='') ++val,len--;
for(re int i=;i<len;++i) s[i]=val[len-i-]-'';
return *this;
}
inline void deal()
{
while(len>&&!s[len-]) len--;
}
node operator + (const node &a) const
{
node res;res.len=;
re int top=max(len,a.len),add=;
for(re int i=;add||i<top;++i)
{
re int now=add;
if(i<len) now+=s[i];
if(i<a.len) now+=a.s[i];
res.s[res.len++]=now%;
add=now/;
}
return res;
}
node operator - (const node &a) const
{
node res; res.len=;re int del=;
for(re int i=;i<len;++i){
re int now=s[i]-del;
if(i<a.len) now-=a.s[i];
if(now>=) del=;
else del=,now+=;
res.s[res.len++]=now;
}
res.deal(); return res;
}
node operator * (const node &a) const
{
node res; res.len=len+a.len;
for(re int i=;i<len;++i)
for(re int j=;j<a.len;++j)
res.s[i+j]+=s[i]*a.s[j];
for(re int i=;i<res.len;++i)
res.s[i+]+=res.s[i]/,res.s[i]%=;
res.deal(); return res;
}
node operator / (const node &a) const
{
node res,cur=;res.len=len;
for(re int i=len-;~i;--i){
cur=cur*,cur.s[]=s[i];
while(cur>=a)
cur-=a,res.s[i]++;
}
res.deal(); return res;
}
node operator % (const node &a) const
{
node res=*this/a;
return *this-res*a;
}
node operator += (const node &a) {*this=*this+a; return *this;}
node operator -= (const node &a) {*this=*this-a; return *this;}
node operator *= (const node &a) {*this=*this*a; return *this;}
node operator %= (const node &a) {*this=*this%a; return *this;}
bool operator < (const node &a) const
{
if(len!=a.len) return len<a.len;
for(re int i=len-;~i;i--)
if(s[i]!=a.s[i]) return s[i]<a.s[i];
return false;
}
bool operator > (const node &a) const {return a<*this;}
bool operator <= (const node &a) const {return !(*this>a);}
bool operator >= (const node &a) const {return !(*this<a);}
bool operator == (const node &a) const {return !(*this>a||*this<a);}
bool operator != (const node &a) const {return *this>a||*this<a;}
}; inline void print(const node &a)
{
for(re int i=a.len-;~i;--i)
printf("%d",a.s[i]); puts("");
}
int n,k,m;
node f[][][][];
int a2,a3,a5,a7;
void solve()
{
node a,b;
a.s[]=;
b.s[]=;
for(int i=;i<=n;i++)
{
a*=;
b*=;
}
b-=a;
print(b);
}
int main()
{
scanf("%d%d", &n, &k);
if(k==)
{
solve();
return ;
}
int t = k;
while (k % == )
a2++,k /= ;
while (k % == )
a3++, k /= ;
while (k % == )
a5++, k /= ;
while (k % == )
a7++, k /= ;
if(k!=)
{
printf("");
return ;
}
f[][][][].s[] = ;
f[][][][].len = ;
for (int i = ; i <= n;i++)
{
for (int j = a2; j >= ;j--)
{
for (int k = a3; k >= ;k--)
{
for (int l = a5; l >= ;l--)
{
for (int m = a7; m >= ;m--)
{
if(j>=)
f[j][k][l][m] = f[j - ][k][l][m] + f[j][k][l][m];//
if(k>=)
f[j][k][l][m] = f[j][k - ][l][m] + f[j][k][l][m];//
if(j>=)
f[j][k][l][m] = f[j - ][k][l][m] + f[j][k][l][m];//
if(l>=)
f[j][k][l][m] = f[j][k][l - ][m] + f[j][k][l][m];//
if(j&&k)
f[j][k][l][m] = f[j - ][k - ][l][m] + f[j][k][l][m];//
if(m>=)
f[j][k][l][m] = f[j][k][l][m - ] + f[j][k][l][m];//
if(j>=)
f[j][k][l][m] = f[j - ][k][l][m] + f[j][k][l][m];//
if(k>=)
f[j][k][l][m] = f[j][k - ][l][m] + f[j][k][l][m];//
}
}
}
}
}
print(f[a2][a3][a5][a7]);
return ;
}
「NOIP模拟赛」数位和乘积(dp,高精)的更多相关文章
- 「NOIP模拟赛」Round 3
Tag 计数+LIS, 二分+ST表, 计数+记搜 A. 改造二叉树 Description 题面 Solution 如果目标序列非严格递增,或者说目标序列是不下降的,那么答案就是 \(n\) 减去最 ...
- 「NOIP模拟赛」Round 2
Tag 递推,状压DP,最短路 A. 篮球比赛1 题面 \(Milky\ Way\)的代码 #include <cstdio> const int N = 2000, xzy = 1e9 ...
- 「CSP-S模拟赛」2019第四场
「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...
- 「CSP-S模拟赛」2019第三场
目录 T1 「POI2007」山峰和山谷 Ridges and Valleys 题目 考场思路(几近正解) 正解 T2 「JOI 2013 Final」 现代豪宅 题目 考场思路(正解) T3 「SC ...
- 【模拟】HHHOJ#251. 「NOIP模拟赛 伍」高精度
积累模拟经验 题目描述 维护一个二进制数,支持如下操作 "+" 该数加 11 "-" 该数减 11 "*" 该数乘 22 "\&q ...
- Solution -「牛客 NOIP 模拟赛」打拳
\(\mathcal{Description}\) 现 \(2^n\) 个人进行淘汰赛,他们的战力为 \(1\sim 2^n\),战力强者能战胜战力弱者,但是战力在集合 \(\{a_m\}\) 里 ...
- 「CSP-S模拟赛」2019第二场
目录 T1 Jam的计数法 题目 考场思路(正解) T2 「TJOI / HEOI2016」排序 题目 考场思路(假正解) 正解 T3 「THUWC 2017」随机二分图 题目 考场思路 正解 这场考 ...
- 「CSP-S模拟赛」2019第一场
目录 T1 小奇取石子 题目 考场思路 正解 T2 「CCO 2017」专业网络 题目 考场思路 题解 T3 「ZJOI2017」线段树 题目 考场思路 正解 这场考试感觉很奇怪. \(T1.T2\) ...
- 「2018-11-05模拟赛」T5 传送机 解题报告
5.传送机(sent.*) 问题描述: 黄黄同学要到清华大学上学去了.黄黄同学很喜欢清华大学的校园,每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍. 我们一般人很可能对 ...
随机推荐
- BUUCTF刷题记录(Web方面)
WarmUp 首先查看源码,发现有source.php,跟进看看,发现了一堆代码 这个原本是phpmyadmin任意文件包含漏洞,这里面只不过是换汤不换药. 有兴趣的可以看一下之前我做的分析,http ...
- 【TencentOS tiny】深度源码分析(4)——消息队列
消息队列 在前一篇文章中[TencentOS tiny学习]源码分析(3)--队列 我们描述了TencentOS tiny的队列实现,同时也点出了TencentOS tiny的队列是依赖于消息队列的, ...
- [Vijos] 遭遇战
背景 你知道吗,SQ Class的人都很喜欢打CS.(不知道CS是什么的人不用参加这次比赛). 描述 今天,他们在打一张叫DUSTII的地图,万恶的恐怖分子要炸掉藏在A区的SQC论坛服务器!我们SQC ...
- 【RocketMQ源码学习】- 1. 入门
为什么读RocketMQ 消息队列在互联网应用中使用较为广泛,学习她可以让我门更加了解使用技术的工作原理 透过学习她的源码,拓宽认知 RocketMQ经历了阿里双十一 有哪些名词 Producer 消 ...
- Qt5教程: (7) 模态/非模态对话框
模态对话框就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭. 非模态对话框就是在被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互. 1. ...
- 一个有趣的C语言问题
这个问题是知乎上的一个问题,看了以后觉得比较有意思.代码短到只有十多行,但是这么短的代码却输出了很奇怪的结果.很多人回答的时候都是站在理论的角度上说明代码的问题,但是实际的问题还是没有说明其中的问题. ...
- 程序员修神之路--为什么有了SOA,我们还用微服务?
菜菜哥,我最近需要做一个项目,老大让我用微服务的方式来做 那挺好呀,微服务现在的确很流行 我以前在别的公司都是以SOA的方式,SOA也是面向服务的方式呀 的确,微服务和SOA有相同之处 面向服务的架构 ...
- C++ 大作业资料总结
一般 C++ 大作业都是用 Qt 来写,Qt 本身带了很多例子,详见:https://doc.qt.io/qt-5/qtexamples.html# 如果你想偷懒的话,直接拿来改就好,或者去 Gith ...
- vue-class-component使用Mixins
vue-class-component提供了mixinshelper函数,以类样式的方式使用mixins.通过使用mixins帮助程序,TypeScript可以推断mixin类型并在组件类型上继承它们 ...
- Kerberos kinit crontab定时任务不生效的问题解决
问题 有这样一个定时任务 1 */12 * * * kinit -kt xxxxxx.keytab principle 这样写每天 12点,执行一次. 但是服务器的应用程序报错: GSS initia ...