noip13
T1
一开始直接丢了个暴力走人50pts,然后开始打表找规律,啥也没找着,最后二十分钟突然看出来了什么,把 \(f_{n,m}\)式子列了一下,发现常数项没啥规律,最后五分钟,突然闪过一丝灵感,但是是错的。
好吧,其实跟正解就差一个常数项,但是没想到把矩阵放棋盘上,也没想到排列组合。
正解:
把这玩意放个矩阵或者说是棋盘上,考虑从当前点走到 \((n,m)\),对答案所造成的贡献,常数项就是走法的方案数。剩下的就是上边的打表找出来的规律
Code
#include<cstdio>
#define MAX 300010
#define re register
#define int long long
namespace OMA
{
int n,m,a,b,ans;
int f1[MAX],f2[MAX];
int bina[MAX],binb[MAX]; // a,b
const int p = 998244353;
int c[MAX<<1],inv[MAX<<1];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline int quickpow(int a,int b)
{
int ans = 1;
while(b)
{
if(b&1)
{ ans = ans*a%p; }
a = a*a%p;
b >>= 1;
}
return ans;
}
inline int C(int n,int m)
{ return c[n]*inv[m]%p*inv[n-m]%p; }
signed main()
{
bina[0] = binb[0] = inv[0] = c[0] = 1;
n = read(),m = read(),a = read()%p,b = read()%p;
for(re int i=1; i<=n; i++)
{ f1[i] = read()%p; binb[i] = b*binb[i-1]%p; }
for(re int i=1; i<=m; i++)
{ f2[i] = read()%p; bina[i] = a*bina[i-1]%p; }
int top = n+m;
for(re int i=1; i<=top; i++)
{ c[i] = i*c[i-1]%p; }
inv[top] = quickpow(c[top],p-2);
for(re int i=top-1; i>=1; i--)
{ inv[i] = (i+1)*inv[i+1]%p; }
for(re int i=n; i>=1; i--)
{ (ans += bina[m]*f1[i]%p*binb[n-i]%p*C(n+m-i-1,m-1)%p) %= p; }
for(re int i=m; i>=1; i--)
{ (ans += binb[n]*f2[i]%p*bina[m-i]%p*C(n+m-i-1,n-1)%p) %= p; }
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
T2
考场没思路,跳了。
正解是个dp 怪不得没思路
首先,这是个树形dp,但题目中给你的,显然并不是一颗普通的树,它有个环,是个环套树,所以考虑把环去掉,怎么去?,删掉环中的一条边即可,那条边? 随便那条,只要是环上的即可,然后,就可以愉快的dp了,dp可类比一下没有上司的舞会
Code
#include<cstdio>
#include<cstring>
#define MAX 1000010
#define re register
namespace OMA
{
int n,a,b,ans;
struct Graph
{
int next;
int to;
}edge[MAX<<1];
int vis[MAX],rt[2];
int cnt=1,head[MAX];
int w[MAX],dp[MAX][2];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline void add(int u,int v)
{
edge[++cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt;
}
inline void dfs1(int u,int fa)
{
if(vis[u])
{ rt[0] = u,rt[1] = fa; return ; }
vis[u] = 1;
for(re int i=head[u]; i; i=edge[i].next)
{
int v = edge[i].to;
if(v!=fa)
{ dfs1(v,u); }
}
}
inline int min(int a,int b)
{ return a<b?a:b; }
inline void dfs2(int u,int fa)
{
dp[u][0] = 0,dp[u][1] = w[u];
for(re int i=head[u]; i; i=edge[i].next)
{
int v = edge[i].to;
if((u==rt[0]&&v==rt[1])||(u==rt[1]&&v==rt[0]))
{ continue ; }
if(v!=fa)
{
dfs2(v,u);
dp[u][0] += dp[v][1];
dp[u][1] += min(dp[v][0],dp[v][1]);
}
}
}
signed main()
{
n = read(),a = read(),b = read();
for(re int i=1; i<=n; i++)
{
int v1 = read(),v2 = read();
w[v1] += a,w[v2] += b;
add(v1,v2),add(v2,v1);
}
dfs1(1,0);
dfs2(rt[0],0),ans = dp[rt[0]][1],dfs2(rt[1],0);
printf("%d\n",min(ans,dp[rt[1]][1]));
return 0;
}
}
signed main()
{ return OMA::main(); }
T3
三道里,比较简单的一道了
首先不难发现,\(i\times j\) 为完全平方数时,约数个数为奇数。所以有了60暴力,直接枚举i,j 统计完全平方数的个数,偶数+1,奇数-1。
60pts
#include<cstdio>
#include<cmath>
#define re register
#define int long long
namespace OMA
{
int n,m,ans;
signed main()
{
scanf("%lld%lld",&n,&m);
for(re int i=1; i<=n; i++)
{
int cnt = 0;
for(re int j=1; j<=m; j++)
{
int tmp = i*j;
int gen = sqrt(tmp);
if(gen*gen==tmp)
{ cnt++; }
}
if(cnt%2==0)
{ ans++; }
else
{ ans--; }
}
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
正解:
首先把i拆成 \(p\times q^{2}\) 的形式,那么j则有 \(p\times r^{2}\) 的形式。
那么对答案产生贡献的 \(j\) 有 \(\sqrt{\frac{m}{p}}\) 个,\(p\) 可以通过线性筛求出。
注意,线性筛是一种方法,并不是单指筛素数,但 \(p\) 是可以通过类比线性筛求素数,求出来,线性筛素数,是去找最小质因子,然后将其倍数都标记掉,类似的,可以通过最小质因子来求 \(p\) 。
Code
#include<cmath>
#include<cstdio>
#define re register
const int top=1e7+10;
int cnt,pri[top];
long long m;
int n,ans,jud[top],p[top];
namespace OMA
{
void opt()
{
p[1] = 1;
for(re int i=2; i<=n; i++)
{
if(!jud[i])
{ pri[++cnt] = jud[i] = p[i] = i; }
for(re int j=1; j<=cnt&&i*pri[j]<=n; j++)
{
if(!(p[i]%pri[j]))
{ p[i*pri[j]] = p[i]/pri[j]; }
else
{ p[i*pri[j]] = p[i]*pri[j]; }
jud[i*pri[j]] = pri[j];
if(!(i%pri[j]))
{ break ; }
}
}
}
signed main()
{
scanf("%d%lld",&n,&m);
opt();
for(re int i=1; i<=n; i++)
{ int tmp = sqrt(m/p[i]); ans += (tmp%2==0)?1:-1; }
printf("%d\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
noip13的更多相关文章
- [Luogu 1966] noip13 火柴排队
[Luogu 1966] noip13 火柴排队 Problem 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之 ...
随机推荐
- windows服务器下MySQL配置字符集
这俩天公司使用.netcore微服务+mysql做项目,mysql在使用的时候总是出现一些字符集的问题,修改utf8或utf8mb4后mysql的服务就启动不了,这里做下记录如果把my.ini中的字符 ...
- 刷算法,这些api不可不知!
大家好,我是老三,最近在刷算法,发现有些api记得不熟,所以整理了一波,如果你也在刷题,赶紧收藏吧! 集合 在刷题中,各种数据结构是我们常常用到的,例如栈实现迭代.哈希存储键值对等等,我们来看看常用集 ...
- 数组去重汇总—v客学院技术分享
上周基础班结束了数组的学习内容,这几天有时间整理了下几种比较常用的数组去重的方法供大家查阅!!!!! 话不多说,直接贴代码吧~~~~~~~ 欢迎大家指正,共同学习,一同进步!!! (php开发,web ...
- Java 获取Word中指定图片的坐标位置
本文介绍通过Java程序获取Word文档中指定图片的坐标位置. 程序运行环境: Word测试文档:.docx 2013 Free Spire.doc.jar 3.9.0 IntelliJ IDEA J ...
- 前端基础html(二)
一.html的概念 1.概念:超文本标记语言. 2.超文本,超链接:超级不仅有文本,图片,还有音频,视频等. 3.html:作用: 显示服务器端的响应结果. 二.互联网三大基石 1.url:统一资 ...
- Python基础之读写xml总结
参考文章:https://blog.csdn.net/weixin_42749767/article/details/82770563 先介绍xml.dom.minidom包,有一个读写的例子 rea ...
- 如何使用Git Flow 进行hotfix
前提是已经安装好git flow并做好配置.安装指导 1 首先确定你的紧急发布应基于那个分支(默认是mater/main分支,)并切换到对应分支. 2 git flow init--该命令会只指导你基 ...
- 构建后端第1篇之---springcloud项目依赖分析
张艳涛写于2021-2-2日 springcloud是springboot工程+cloud依赖,从这个角度来分析,使用springcloud实际上就是添加springcloud的某个以来比如eurek ...
- JS 高级程序设计3.5.1一元操作符 递增和递减操作符++ --
var age =29 ++age; 在这个例子中,前置递增操作符把age的值变成了30.实际上,执行这个前置递增操作符与执行 一下操作的效果相同: var age=29; age =age+1;// ...
- CC2B本地环境搭建步骤及部署问题解决
由于最近的项目是之前没接触过的netbeans+glassfish,记录一下最近在工作中搭建本地环境的步骤及遇到的一些问题解决方法: 1.配置java jdk 此过程中遇到一个问题就是在配置系统环境变 ...