NOIP模拟13「工业题·卡常题·玄学题」
T1:工业题
基本思路
这题有一个重要的小转化:
我们将原来的函数看作一个矩阵,\(f(i,j-1)*a\)相当于从\(j-1\)向右走一步并贡献a,\(f(i-1,j)*b\)相当于从\(i-1\)向下走一步并贡献b
那么问题就转化成了求从第\(0\)行与第\(0\)列的所有点走到点\((m,n)\)的所有方案数的总贡献
在一个点,对于他之前的点的所有走法,他都有可能向下或右走并带来贡献,所以是统计所有方案数。
易知从点\((i,j)\)到点\((m,n)\)的走的步数是\(m-i+n-j)\),又由于在每一个点都有向下或向右走的可能,我们可以只关注向下(或向右),看每一步向下(或向右)走发生在哪个点,那么方案数就是\(C_{n+m-i}^{n-i}\)(从第0列出发)及\(C_{n+m-i}^{m-i}\)(从第0行出发)
你这么打了,然后你WA了。。。。。。
为什么?
注意:这里的C考虑的是决策点,但是,第0行(列)的点一定会向下(右)走,是不会有决策的,因而正确的式子是:
\]
上代码:
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
#define ll long long
#define rr register
const int SIZE=3e5+4;
const int mod=998244353;
int n,m;
ll a,b,ans;
ll jc[SIZE<<1],inv[SIZE<<1];
ll fn[SIZE],fm[SIZE];
ll b_,a_;
ll qpow(ll base,ll exp)
{
rr ll ret=1ll;
while(exp)
{
if(exp&1) ret=ret*base%mod;
base=base*base%mod;
exp>>=1ll;
}
return ret;
}
inline ll C(ll x,ll y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
ll read1()
{
rr ll x_read=0ll,y_read=1ll;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9')
{
if(c_read=='-') y_read=-1;
c_read=getchar();
}
while(c_read<='9'&&c_read>='0')
{
x_read=x_read*10+(c_read^48);
c_read=getchar();
}
return x_read*y_read;
}
int read2()
{
rr int x_read=0ll,y_read=1ll;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9')
{
if(c_read=='-') y_read=-1;
c_read=getchar();
}
while(c_read<='9'&&c_read>='0')
{
x_read=x_read*10+(c_read^48);
c_read=getchar();
}
return x_read*y_read;
}
};
using namespace STD;
int main()
{
n=read2(),m=read2(),a=read1(),b=read1();
a%=mod,b%=mod;
a_=qpow(a,m);
b_=qpow(b,n);
//由于后面a^m与b^n会大量用到,所以预处理
for(rr int i=1;i<=n;i++){fn[i]=read1();fn[i]%=mod;}
for(rr int i=1;i<=m;i++){fm[i]=read1();fm[i]%=mod;}
jc[0]=inv[0]=1ll;
for(rr int i=1;i<=n+m;i++){jc[i]=1ll*i*jc[i-1]%mod;inv[i]=qpow(jc[i],mod-2);}
for(rr int i=1;i<=n;i++)
ans=(ans+fn[i]*C(n+m-i-1,m-1)%mod*qpow(b,n-i)%mod*a_%mod)%mod;
for(rr int i=1;i<=m;i++)
ans=(ans+fm[i]*C(n+m-i-1,n-1)%mod*b_%mod*qpow(a,m-i)%mod)%mod;
int x=printf("%lld",ans);
}
T2:
基本思路:
考场上想的普通DP,不对。
实际上是树形DP
实际上可以将Y方点看作边,然后将X方点看作点,\(n\)个点\(n\)条边,很明显,去掉一条边后就是树,我们的任务就是求能将所有的边都覆盖的最小代价,一条边被覆盖是指它的两个端点至少有一个被选。
我们可以判出环来然后删去环里的任一条边,然后以删掉的边的端点跑DP即可
很明显树形DP,DP式就不写在这了,自己推吧,推不出来就自己上代码里找吧。
状态数组\(c[i][j](j=0,1)\)表示i被选(j=1)或不被选(j=0)是以他为根的子树的最小代价。
注意被删掉的边也要被覆盖,所以要在两个端点被选的情况里取min
代码:
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
#define ll long long
#define rr register
#define pp pair<int,int>
#define fi first
#define se second
#define min(x,y) (x<y?x:y)
#define inf LONG_LONG_MAX
#define IT set<int>::iterator
const int SIZE=1e6+4;
int n,root;
ll ans=inf,a,b;
set<int> to[SIZE];
ll val[SIZE];
ll c[SIZE][2];
bool vis[SIZE];
pp edge;
void dfs(int x,int f)
{
static bool ret=0;
vis[x]=1;
for(IT it=to[x].begin();it!=to[x].end();it++)
{
if(*it==f) continue;
if(vis[*it]){edge.fi=x,edge.se=*it;ret=1;return;}
dfs(*it,x);
if(ret) return;
}
}
void DP(int now,int f)
{
//儿子与父亲必须至少有一个选
for(IT it=to[now].begin();it!=to[now].end();it++)
{
if(*it==f) continue;
DP(*it,now);
c[now][1]+=min(c[*it][0],c[*it][1]);
c[now][0]+=c[*it][1];
//鄙视你的智商,连我都推出来的式子你还推不出来过来看。。。。
}
c[now][1]+=val[now];
}
int read()
{
rr int x_read=0,y_read=1;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9')
{
if(c_read=='-') y_read=-1;
c_read=getchar();
}
while(c_read<='9'&&c_read>='0')
{
x_read=(x_read*10)+(c_read^48);
c_read=getchar();
}
return x_read*y_read;
}
};
using namespace STD;
int main()
{
n=read(),a=read(),b=read();
for(rr int i=1;i<=n;i++)
{
int x1=read(),x2=read();
to[x1].insert(x2),to[x2].insert(x1);
val[x1]+=a,val[x2]+=b;
}
dfs(1,1);
to[edge.fi].erase(edge.se);
to[edge.se].erase(edge.fi);
root=edge.fi;
DP(root,root);
ans=min(c[root][1],ans);
for(rr int i=1;i<=n;i++) c[i][0]=c[i][1]=0;
root=edge.se;
DP(root,root);
ans=min(ans,c[root][1]);
printf("%lld",ans);
}
T3:玄学题
基本思路
当我看到-1的时候就已经想到要判指数的奇偶了,但是不会高效地判。
其实想来也很简单(事后诸葛亮),\(d\)为偶数的情况不决定奇偶,只有奇数的情况才决定,而约数数为奇数只有完全平方数一种情况。
证明:
对于每个数,他本身以及1都是他的约数,这就有两个约数了。
假如一个数能被某个数整除,这个数及得数都是其约数,那么,除了某个数平方是这个数,那么他的约数一定成对存在。
而假如有个数的平方是这个数,那么它的商还是他自己,那么他这一“对”就只有他自己。
这个平方数约数个数为奇数。
假如有\(i=p*x^2\)
要想使\(d(i*j)\)是奇数那么j必须满足\(j=p*y^2\),那么我们只要统计\([1,m]\)内有几个j满足条件即可。
首先我们可以写一个线性筛法求出每个i的p,并记录。
线性筛法:
p[1]=1;
for(rr int i=2;i<=en;i++)
p[i*i]=1;
for(rr int i=2;i<=n;i++)
if(!p[i])
{
p[i]=i;
for(rr int j=2;j<=en;j++)
{
if(j*j*i>n) break;
p[j*j*i]=i;
}
}
然后,就有j的个数
\]
\]
证明:
平方在[1,m]范围内的数最多有\(\sqrt{m}\)个那么平方后\(p\)倍还在范围内的就有\(\sqrt{\frac{m}{p}}\)个
那么我们的算法就是\(O(n)\)的了。
代码:
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
#define ll long long
#define rr register
const int SIZE=1e7+4;
int n,ans;
ll m;
int p[SIZE];
ll read()
{
rr ll x_read=0,y_read=1;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9')
{
if(c_read=='-') y_read='-';
c_read=getchar();
}
while(c_read<='9'&&c_read>='0')
{
x_read=(x_read*10)+(c_read^48);
c_read=getchar();
}
return x_read*y_read;
}
};
using namespace STD;
int main()
{
n=read(),m=read();
int en=sqrt(n);
p[1]=1;
for(rr int i=2;i<=en;i++)
p[i*i]=1;
for(rr int i=2;i<=n;i++)
if(!p[i])
{
p[i]=i;
for(rr int j=2;j<=en;j++)
{
if(j*j*i>n) break;
p[j*j*i]=i;
}
}
for(rr int i=1;i<=n;i++)
{
ll x=sqrt(m/(ll)p[i]);
if(x&1ll) ans--;
else ans++;
}
printf("%d",ans);
}
NOIP模拟13「工业题·卡常题·玄学题」的更多相关文章
- HZOI20190906模拟39 工业,卡常,玄学
题面:https://www.cnblogs.com/Juve/articles/11484209.html 工业: 推一个式子,AC 没有用组合数....推了2个多小时 我sbsbsbsbsbsbs ...
- NOIP 模拟 $13\; \text{工业题}$
题解 本题不用什么推式子,找规律(而且也找不出来) 可以将整个式子看成一个 \(n×m\) 矩阵 考虑 \(f_{i,j}\),它向右走一步给出 \(f_{i,j}×a\) 的贡献,向下走一步给出 \ ...
- NOIP模拟测试「简单的区间·简单的玄学·简单的填数·简单的序列」
简单的区间 $update$ 终于$AC$了 找到$(sum[r]+sum[l](sum表示以中间点为基准的sum)-mx)\%k==0$的点 注意这里$sum$表示是以$mid$为基准点,(即$su ...
- NOIP模拟测试39,思维禁锢专场「工业题·玄学题·卡常题」
工业题 题解 抱歉,题解没时间写了 代码 #include<bits/stdc++.h> using namespace std; #define ll long long #define ...
- Noip模拟13 2021.7.13:再刚题,就剁手&&生日祭
T1 工业题 这波行列看反就非常尴尬.....口糊出所有正解想到的唯独行列看反全盘炸列(因为和T1斗智斗勇两个半小时...) 这题就是肯定是个O(n+m)的,那就往哪里想,a,b和前面的系数分开求,前 ...
- noip模拟44[我想我以后会碰见计数题就溜走的]
noip模拟44 solutions 这一场抱零的也忒多了,我也只有45pts 据说好像是把几套题里面最难的收拾出来让我们考得 好惨烈啊,这次的考试我只有第一题骗了40pts,其他都抱零了 T1 Em ...
- NOIP 模拟 $13\; \text{卡常题}$
题解 一道环套树的最小点覆盖题目,所谓环套树就是有在 \(n\) 个点 \(n\) 条边的无向联通图中存在一个环 我们可以发现其去掉一条环上的边后就是一棵树 那么对于此题,我们把所有 \(x\) 方点 ...
- NOIP模拟测试13「矩阵游戏·跳房子·优美序列」
矩阵游戏 考试时思路一度和正解一样,考试到最后还是打了80分思路,结果80分打炸了只得了40分暴力分 题解 算出来第一列的总值,每次通过加每两列之间的差值得出下一列的总值 算第一列我们只需要让当前点* ...
- NOIP 模拟 $13\; \text{玄学题}$
题解 题如其名,是挺玄学的. 我们发现每个值是 \(-1\) 还是 \(1\) 只与它的次数是奇是偶有关,而 \(\sum_j^{j\le m}d(i×j)\) 又只与其中有多少个奇数有关 对于 \( ...
随机推荐
- Discuz 7.x/6.x 全局变量防御绕过导致代码执行
地址 http://192.168.49.2:8080/viewthread.php?tid=13&extra=page%3D1 安装成功后,找一个已存在的帖子,向其发送数据包,并在Cooki ...
- 大数据学习(10)—— Hive进阶
前面提到了Hive的知识点非常零散,我不知道该怎么把这些知识点分类,跟SQL关系没那么大的就放在这一篇吧. Hive Serde 参考Hive Serde Serde是啥 Serde是序列化和反序列化 ...
- js hook
//cookie hook (function () { 'use strict'; var cookie_cache = document.cookie; Object.defineProperty ...
- BSTestRunner增加历史执行记录展示和重试功能
之前对于用例的失败重试,和用例的历史测试记录存储展示做了很多的描述呢,但是都是基于各个项目呢,不方便使用,为了更好的使用,我们对这里进行抽离,抽离出来一个单独的模块,集成到BSTestRunner中, ...
- ElasticSearch进阶检索
ElasticSearch进阶检索 入门检索中讲了如何导入elastic提供的样本测试数据,下面我们用这些数据进一步检索 一.SearchAPI ES 支持两种基本方式检索 : 1.一种是通过使用 R ...
- Nginx 解析漏洞
目录 漏洞复现 漏洞成因 修复方案 参考链接 该漏洞与Nginx.php版本无关,属于用户配置不当造成的解析漏洞. 漏洞复现 访问http://172.17.0.1/uploadfiles/nginx ...
- 一、MinIO的基本概念
MinIO的官方网站非常详细,以下只是本人学习过程的整理 一.MinIO的基本概念 二.Windows安装与简单使用MinIO 三.Linux部署MinIO分布式集群 四.C#简单操作MinIO 一. ...
- MobSF移动安全扫描平台本地化部署与简单汉化
在之前的文章MobSF移动安全扫描平台环境搭建与试用中,我们用docker进行了搭建,那么我们如何在本地直接搭建呢,其实也是很简单的. 本地化部署 我们在本地安装 其实是很简单的,里面有两个文件,在不 ...
- 热血动漫番太好看了!用Python爬取了1T的动漫,内存都爆了
最近被室友安利热血动漫番<终末的女武神>和<拳愿阿修罗>,太上头了周末休息熬夜看完了.不过资源不太好找,辣条一怒爬取了资源,这下可以看个够了.室友崇拜连连,想起了我的班 ...
- Python3实现Two-Pass算法检测区域连通性
技术背景 连通性检测是图论中常常遇到的一个问题,我们可以用五子棋的思路来理解这个问题五子棋中,横.竖.斜相邻的两个棋子,被认为是相连接的,而一样的道理,在一个二维的图中,只要在横.竖.斜三个方向中的一 ...