[NOIP模拟33]反思+题解
又考了一次降智题……
拿到T1秒出正解(可能是因为我高考数学数列学的海星?),分解质因数以后用等比数列求和计算每个因子的贡献。但是当时太过兴奋把最后的$ans \times =$打成了$ans +=$,还过掉了sb样例。觉得自己AC稳了就先交了。
然后去看T3。没什么思路就先打了个暴力,以为最后一个看似不可做的点是给特判分的就打了一堆特判(没想到真的是用来防AK的)。
最后搞T2,实在是搞不懂题就打了个乱搞,样例也可过就扔掉了。
最后对拍T1的时候发现答案完全不对,因为只剩30min辽所以我当场慌的一批,压根就没想改之前的代码,xjb打了一个70分的暴力赶在考试结束前调了出来。
考后4minA掉T1。一个字符的差距。
如果在最后发现自己之前的代码有错误,一定要先想能不能改过来再考虑打暴力止损。一开始心态平稳时想的思路大概率是正确的,如果对拍出错很有可能是细节问题。
A.春思
水题。对A分解质因数,把因子的次数都乘上B就得到了原数。之后考虑因数和$d(x)$的积性函数性质。对于每一个质因子次幂,它的约数和相当与一个等比数列和,那么把每一个质因子次幂的约数和乘起来就得到了最终结果。(别告诉我您不知道等比数列求和公式)
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=9901;
const int N=3e6+5;
ll a,b;
ll fact[N],cnt,mi[N],ans=1;
ll qpow(ll x,ll y)
{
ll res=1;x=x%mod;
while(y)
{
if(y&1)res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
int main()
{
scanf("%lld%lld",&a,&b);
ll tmp=a;
for(ll i=2;i*i<=tmp;i++)
{
if(tmp%i==0)
{
fact[++cnt]=i;ll num=0;
while(tmp&&tmp%i==0)num++,tmp/=i;
mi[cnt]=num;
}
}
if(tmp>1)fact[++cnt]=tmp,mi[cnt]=1;
for(int i=1;i<=cnt;i++)
{
ll m=mi[i]*b;
(ans*=(qpow(fact[i],m+1)-1)*qpow(fact[i]-1,mod-2)%mod)%=mod;
}
cout<<ans%mod<<endl;
return 0;
}
B.密州盛宴
显然,如果想符合要求就必须保证每个人随时都在吃,那么自然0越靠前越优,而且0的个数不能超过n个。
考虑比较直观地确定方案是否合法的方式。把0的值赋成-1,从序列末尾往前扫,维护后缀和。一旦某时刻后缀和$< -1$,就可以确定方案是不合法的。
所以可以从末尾挑C个0挪到开头,二分C即可。这是70分的做法。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=2e7+5;
int n,m,a[N],tot;
bool check(int x)
{
int val=x,sum=0;
for(int i=2*n;i;i--)
{
if(sum<=-2)return 0;
if(a[i]==-1)
if(val){val--;continue;}
sum+=a[i];
}
if(sum+x*(-1)<=-2)return 0;
return 1;
} void work()
{
tot=0;
char s[1000005];
for(int i=1;i<=m;i++)
{
scanf("%s",s+1);int len=strlen(s+1),tmp;
scanf("%d",&tmp);
while(tmp--)
for(int j=1;j<=len;j++)
a[++tot]=(s[j]=='1'?1:-1);
}
int cnt0=0;
for(int i=1;i<=2*n;i++)
if(a[i]==-1)cnt0++;
if(cnt0>n)
{
puts("-1");
return ;
}
int l=0,r=2*n,res;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid))r=mid-1,res=mid;
else l=mid+1;
}
cout<<res<<endl;
} int main()
{
while(scanf("%d%d",&n,&m)==2)
{
if(!n&&!m)break;
work();
}
return 0;
}
可以发现,如果从已经扫到的0里挑一个扔到前面去,目前的后缀和就会+1。所以答案转化为求整个序列后缀和的最小值后取绝对值再-1。
对于每一个给出的循环节,计算这一段的后缀和,并记录过程中后缀和的最小值。对于一整段的后缀和是否>0分类讨论一下更新答案即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
ll n;
int m;
vector<int> a[100005];
ll num[100005];
void work()
{
for(int i=1;i<=m;i++)a[i].clear();
char s[100005];
ll cnt0=0;
for(int i=1;i<=m;i++)
{
ll cnt00=0;
scanf("%s",s+1);
int len=strlen(s+1);
for(int j=1;j<=len;j++)
a[i].push_back(s[j]=='1'?1:-1),cnt00+=(s[j]=='0');
scanf("%lld",&num[i]);
cnt00*=num[i];
cnt0+=cnt00;
}
//cout<<"The num of 0: "<<cnt0<<endl;
if(cnt0>n)
{
puts("-1");return ;
}
ll sum=0,cnt=0,ans=0x3f3f3f3f;
for(int k=m;k;k--)
{
cnt=0;ll minn=0x3f3f3f3f;
int sz=a[k].size();
for(int i=sz-1;i>=0;i--)
{
cnt+=a[k][i];
minn=min(minn,cnt);
}
if(cnt>0)
ans=min(ans,sum+minn);
else
ans=min(ans,sum+cnt*(num[k]-1)+minn);
sum+=cnt*num[k];
}
ans=abs(ans)-1;
cout<<(ans>=0?ans:0)<<endl;
} int main()
{
while(scanf("%lld%d",&n,&m)==2)
{
if(!n&&!m)break;
work();
}
return 0;
}
C.赤壁情
又是一道神dp……
如果我们能把每一个赤壁之意对应的方案数都求出来,那么就能统计一下再除个阶乘得到答案了。所以把这题转化成计数dp。
我们把形成排列的过程看作把$1,2,...n$放到$n$个位置的过程。为了能够转移,应该把这n个数从小到大逐个放入。
定义状态数组$f[i][j][k][l]$。i表示从小到大放到了i,j表示目前的序列上有j段数(它们被一些空位隔开),k表示边界(最左和最右端)放了几个数(0 or 1 or 2),l表示目前赤壁之意为l。
考虑插入第i个数对总赤壁之意的贡献:
具体转移还是很繁琐的,有13个转移方程(可以合并成5个)。我们以其中的一个为例:
$f[now][j][0][l]+=f[pre][j][0][l]*j*2;$
它的含义是:插入一个数,并且这个数位于一段的左右端点(恰好延长了一段,没有单独成段或连接左右两段),那么它的方案可以是之前基础上从j段里选一个放,并且每一个都可以选左右两端。且对目前的赤壁之意没有影响。
以此类推转移即可。第一维要滚动,因为要枚举段数所以提前算一下范围,还有就是一开始赤壁之意可能为负所以集体加上一个base防止下标溢出。
至于最后一个防AK点……__float128水过好了QAQ。
#include<cstdio>
#include<iostream>
#include<cstring>
#define re register
using namespace std;
const int base=5005;
int n,m,K;
int part[105];
namespace qj
{
__float128 f[2][105][4][10015];
void Main()
{
int now=1,pre=0;
f[now][1][0][-2+base]=1;
f[now][1][1][-1+base]=2;
f[now][1][2][base]=1;
part[1]=1;
for(re int i=2;i<=n;i++)
{
now^=1;pre^=1;
part[i]=min(i,n-i+1);
int fw=min(5000,i*(i+1));
for(re int j=1;j<=part[i];j++)
for(re int l=-fw+base;l<=fw+base;l++)
for(re int k=0;k<=2;k++)
f[now][j][k][l]=0; for(re int j=1;j<=part[i-1];j++)
{
for(re int l=-fw+base;l<=fw+base;l++)
{
#define val0 f[pre][j][0][l]
#define val1 f[pre][j][1][l]
#define val2 f[pre][j][2][l]
//cout<<i<<' '<<val0<<' '<<val1<<' '<<val2<<endl;
f[now][j+1][0][l-i*2]+=val0*(j+1);//1
f[now][j][0][l]+=val0*j*2;//2
f[now][j-1][0][l+i*2]+=val0*(j-1);//3
f[now][j+1][1][l-i]+=val0*2;//4
f[now][j][1][l+i]+=val0*2;//5-----------------------
f[now][j+1][1][l-2*i]+=val1*j;//6
f[now][j][1][l]+=val1*(j*2-1);//7
f[now][j-1][1][l+2*i]+=val1*(j-1);//8
f[now][j+1][2][l-i]+=val1;//9
f[now][j][2][l+i]+=val1;//10----------------------
f[now][j+1][2][l-2*i]+=val2*(j-1);//11
f[now][j][2][l]+=val2*(j*2-2);//12
f[now][j-1][2][l+2*i]+=val2*(j-1);//13
}
} }
__float128 ans=0;
for(re int i=m;i<=base;i++)
ans+=f[now][1][2][i+base];
for(re int i=2;i<=n;i++)
ans/=1.0*i;
printf("%d",(int)ans);
ans-=(int)ans;
putchar('.');
for(re int i=1;i<=K;i++)
{
ans*=10.0;
int t=(ans+(i==K?.5:0));
printf("%d",t);
ans-=t;
}
printf("\n");
}
}
double f[2][105][4][10015];
int main()
{
scanf("%d%d%d",&n,&m,&K);
if(K>=15)
{
qj::Main();
return 0;
}
int now=1,pre=0;
f[now][1][0][-2+base]=1;
f[now][1][1][-1+base]=2;
f[now][1][2][base]=1;
part[1]=1;
for(re int i=2;i<=n;i++)
{
now^=1;pre^=1;
part[i]=min(i,n-i+1);
int fw=min(5000,i*(i+1));
for(re int j=1;j<=part[i];j++)
for(re int l=-fw+base;l<=fw+base;l++)
for(re int k=0;k<=2;k++)
f[now][j][k][l]=0; for(re int j=1;j<=part[i-1];j++)
{
for(re int l=-fw+base;l<=fw+base;l++)
{
#define val0 f[pre][j][0][l]
#define val1 f[pre][j][1][l]
#define val2 f[pre][j][2][l]
//cout<<i<<' '<<val0<<' '<<val1<<' '<<val2<<endl;
f[now][j+1][0][l-i*2]+=val0*(j+1);//1
f[now][j][0][l]+=val0*j*2;//2
f[now][j-1][0][l+i*2]+=val0*(j-1);//3
f[now][j+1][1][l-i]+=val0*2;//4
f[now][j][1][l+i]+=val0*2;//5-----------------------
f[now][j+1][1][l-2*i]+=val1*j;//6
f[now][j][1][l]+=val1*(j*2-1);//7
f[now][j-1][1][l+2*i]+=val1*(j-1);//8
f[now][j+1][2][l-i]+=val1;//9
f[now][j][2][l+i]+=val1;//10----------------------
f[now][j+1][2][l-2*i]+=val2*(j-1);//11
f[now][j][2][l]+=val2*(j*2-2);//12
f[now][j-1][2][l+2*i]+=val2*(j-1);//13
}
} }
double ans=0;
for(int i=m;i<=base;i++)
ans+=f[now][1][2][i+base];
for(double i=2.0;i<=n;i+=1.0)
ans/=i;
switch(K)
{
case 0:printf("%d\n",(int)ans);break;
case 1:printf("%.1lf\n",ans);break;
case 2:printf("%.2lf\n",ans);break;
case 3:printf("%.3lf\n",ans);break;
case 4:printf("%.4lf\n",ans);break;
case 5:printf("%.5lf\n",ans);break;
case 6:printf("%.6lf\n",ans);break;
case 7:printf("%.7lf\n",ans);break;
case 8:printf("%.8lf\n",ans);break;
}
return 0;
}
[NOIP模拟33]反思+题解的更多相关文章
- noip模拟33[进阶啦啦啦]
noip模拟33 solutions 不知道该咋说,这场考试其实是我这三四场以来最最最最最顺心的一场了 为啥呢?因为我这回思考有很多结果,得到了脑袋的回复 就是你想了半个小时就有了一点点头绪,那感觉就 ...
- noip模拟33
\(\color{white}{\mathbb{失足而坠千里,翻覆而没百足,名之以:深渊}}\) 这场考试的时间分配非常不科学 开题试图想 \(t1\) 正解,一个半小时后还是只有暴力,特别惊慌失措 ...
- Noip模拟33垫底反思 2021.8.8
T1 Hunter 考场上没写$%p$挂了25分.也是很牛皮,以后打完过了样例一定要检查 因为样例太小了......很容易忘记%%%% 正解随便手模就出来了. 1 #include<bits/s ...
- 一些noip模拟题一句话题解
Problem A: 序列 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 12 Solved: 9[Submit][Status][Web Boar ...
- 【DP】【构造】NOIp模拟题 演讲 题解
极其考思维的好题 题目背景 众所周知,$\mathrm{Zdrcl}$是一名天天$\mathrm{AK}$的高水平选手. 作为一民长者,为了向大家讲述自己$\mathrm{AK}$的经验,他决 ...
- NOIP模拟 33
苏轼三连一脸懵逼 然而既惨者就是没素质 T1是正解思路 然而因为直接从暴力修改过来并且忘了把求约数改成求质约数并且由于快速幂打的有缺陷等 没 有 A C ! 如 果 A C rank1就是俺的了! ( ...
- [NOIP模拟]文本编辑器 题解
bsoj5089 文本编辑器 /* 题意描述 九发明了一个完美的文本编辑器.这个编辑器拥有两个光标(cursor),所以九能够同时在两处地方插入和删除文本.这个编辑器除了正常的编辑功能以外,还有一些只 ...
- [NOIP模拟测试38]题解
来自达哥的问候…… A.金 显然本题的考察点在于高精而不是裴蜀定理 根据裴蜀定理易得答案为Yes当且仅当$gcd(n,m)=1$,那么考虑怎么在高精度下判互质. 如果$n,m$都能被2整除,那么显然不 ...
- 8.8考试总结(NOIP模拟33)[Hunter·Defence·Connect]
无法逃避的是自我,而无法挽回的是过去. 前言 还算可以,不过 T1 少 \(\bmod\) 了一下挂了 25pts,T2 没看清题面挂了 27pts. 下回注意吧.. T1 Hunter 解题思路 感 ...
随机推荐
- 解决“element表单验证输入的数字检测出来是string”的问题
form表单: 校验规则: 注意:一.数字类型的验证需要在 v-model 处加上 .number 的修饰符,这是 Vue 自身提供的用于将绑定值转化为 number 类型的修饰符.二.校验中是否添加 ...
- 题解 SP4033 【PHONELST - Phone List】
水一发trie板子~ 先说这个题怎么套上板子 首先我们判断是否有前缀可以边插入边判断 当我们经过了一个完整的字符串(即当前节点到了一个有标记的节点上) 就是有前缀 我们当然也可以无脑先判断一发(比如我 ...
- Html5 学习笔记 --》布局
不推荐: 浮动布局: footer 设置 clear : both 清理浮动 | header | |边 | | |内 | 内容 ...
- The 13th Chinese Northeast Collegiate Programming Contest(B C E F H J)
B. Balanced Diet 思路:把每一块选C个产生的价值记录下来,然后从小到大枚举C. #include<bits/stdc++.h> using namespace std; ; ...
- Java实验报告(四)&第六周学习总结
班级 计科二班 学号 20188425 姓名 IM 完成时间2019/10/07 评分等级 一.实验目的 (1)掌握类的继承 (2)变量的继承和覆盖,方法的继承,重载和覆盖的实现: 二.实验的内容 ( ...
- 年度重大升级,IntelliJ IDEA 2019.2 稳定版发布
文章转载自 OSCHINA 社区 [http://www.oschina.net] 期待已久. 7月24日,JetBrains 正式发布了 IntelliJ IDEA 2019.2 稳定版. 作为 I ...
- luoguP1313 计算系数 题解(NOIP2011)
P1313 计算系数 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cm ...
- How to compile Linux kernel in fedora 6
前提:已裝好Fedora 6 core 2.6.18 ,在 Fedora 6 中compile linux kernel.1.下載 Fedora 6 core 2.6.18 http://www.ke ...
- rabbitmq-5-案例1-简单的案例
最简单的案例: https://gitee.com/n_zhe/rabbitmq-demo 通过简单的例子分析mq是怎样发送和拉取消息的: quickStart中的简单案例 通过简单的案例来 ...
- 【转载】linux查看端口状态相关命令
具体命令移步:https://www.cnblogs.com/cxbhakim/p/9353383.html