Problem A 

给出一个$n$个点$m$条边的仙人掌图(每条边最多处于一个简单环中)。

使用$c$种颜色对这张图中的顶点染色,使得每一条无向边连接的两个点颜色不同。

求染色的方案数,$mod \ 998244353$的值。

对于$100\%$的数据满足,$ 1 \leq n,m \leq 10^6$

Solution :

  对于一棵树的答案非常简单就是$c \times (c-1) ^ {n-1}$

  对于一个大环,我们不妨计算这个环上的方案数。

  设$f(n)$表示含有$n$个点的环上使用$c$种颜色染色的方案数,

  非常显然,$f(1) = c$ , $f(2) = c(c-1)$.

  若$c \geq 3$ 那么考虑对于所有节点不能和前一个刚被染色的节点重复染色,方案数就是$c \times (c-1)^{n-1}$

  然后考虑,最后一个点和第一个点的颜色不能重复,若重复,我们可以将其看做一个点,那么就变成了一个子问题。

  最终,$f(n) = c \times (c-1)^{n-1} - f(n-1)$

  对于仙人掌图我们考虑v-DCC缩点(即找点双联通分量)  

  对于一个点,可能在多个简单环里。

  那么对于这个点,只要被一个环计算过,那么在计算剩余环的时候应当认为这个点的颜色既定。

  所以,若多于一个点在$k$个简单环里,我们只需要将总方案数直接除以$c^{k-1}$即可,这是由于该点在其他$k-1$个环中被认为可以被染$c$种颜色,然而事实上,这个点的颜色在第一个环包含它的时候已经被计算。

  所以,本题只需要进行一遍tarjan的v-DCC缩点即可。

  复杂度$O(n)$

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e6+10,mo=998244353;
int dfn[N],low[N],n,m,tot,head[N],cnt,blo[N],f[N],c;
vector<int>dcc[N];
stack<int>s;
struct rec{int pre,to;
}a[N<<2];
void adde(int u,int v) {a[++tot].pre=head[u];a[tot].to=v;head[u]=tot;
}
int Pow(int x,int n) {int ans = 1;while (n) {if (n&1) ans=ans*x%mo;x=x*x%mo;n>>=1;}return ans%mo;
}
void tarjan(int u) {dfn[u] = low[u] = ++dfn[0]; s.push(u);for (int i=head[u];i;i=a[i].pre){int v=a[i].to; if (!dfn[v]) {tarjan(v); low[u]=min(low[u],low[v]);if (low[v]>=dfn[u]) {int z; ++cnt;do {z = s.top(); s.pop();dcc[cnt].push_back(z);blo[z]++;}while (v!=z);dcc[cnt].push_back(u);blo[u]++;}} else low[u] = min(low[u],dfn[v]);}
}main()
{scanf("%lld%lld%lld",&n,&m,&c);for (int i=1;i<=m;i++) {int u,v; scanf("%lld%lld",&u,&v);adde(u,v); adde(v,u);}f[1] = c; f[2] = c*(c-1) % mo;for (int i=3;i<=n;i++) f[i]=((c*Pow(c-1,i-1)%mo-f[i-1])%mo+mo)%mo;tarjan(1);int ans = 1,ret = 0;for (int i=1;i<=n;i++) ret+=blo[i]-1;for (int i=1;i<=cnt;i++)ans = ans*f[dcc[i].size()]%mo;int ni = Pow(c,mo-2);   ans = ans * Pow(ni,ret) % mo;printf("%lld\n",ans);return 0;
}

A.cpp

Problem B

有一个集合S,初始时为空.给定$n,k$

每一次操作,你可以选择1到n中的任意一个不在S中的元素i,并将其加入S,此时如果i-2也在S中,则将i-2从S中删除,

如果i+k也在S中,则将i+k从S中删除。该操作可以进行任意多次。郝仁想知道总共有多少种不同的S,对998244353取模

对于$100\%$的数据$n \leq 300$

Solution :

  首先将集合转化为一个有向图,对于每一个$i$若存在$i-2$和$i+k$,则从$i$连出一条边。

  这样本题就转化为一个图上的计数题。

  • 若$k$为偶数。

    显然序号为奇数和序号为偶数互不干扰,我们可以将奇数序号和偶数序号的分别进行考虑。

    问题便转化为有$n$个数里面选择若干个数,最多可以连续选择$m$个数字,方案数。

    最后将偶数的方案总数乘以奇数的方案总数即可。

    于是我们定义$f_{i,j}$表示前$i$个数字,当前已经连续选择$j$个数字,方案总数。

    转移可以采用刷表法:$f_{i+1,0}+=f_{i,j} , f_{i+1,j+1}+=f_{i,j}$

    复杂度是$O(nm)$的。

  • 若$k$为奇数。

    奇数序号和偶数序号相关,我们可以将$1  - n$的序号从小到大从上到下,奇数在左边,偶数在右边。

    $i$和$i+k$对齐,这样构成的矩阵,高是$\left \lfloor \frac{n+1}{2} \right \rfloor+ \left \lfloor \frac{k}{2} \right \rfloor$

    其中,右侧偶数非空的区间是$[1,\left \lfloor \frac{n}{2}  \right \rfloor]$

    左侧奇数的非空区间是$[\left \lfloor \frac{k}{2} \right \rfloor , \left \lfloor \frac{n+1}{2} \right \rfloor+ \left \lfloor \frac{k}{2} \right \rfloor]$

    上述结论是基本性质,归纳可证。

    考虑一个dp,设$f[i][j][k]$表示当前已经考虑到第$i$层了(从上到下,层数从$1$ 到 $\left \lfloor \frac{n+1}{2} \right \rfloor+ \left \lfloor \frac{k}{2} \right \rfloor$), 在右侧偶数已经连续选择了$j$个元素(为0则为空),在左侧奇数最多连续选择了$k$个元素,且必须包含一个拐弯(我们认为从偶数列跳到奇数列为一个"拐弯")

    我们考虑第$i$层,左选/不选,右选/不选的情况,就可以得到四个DP方程。

    即

  • (左右都不选择,无限制)  : f[i+1][0][0]=f[i][j][k]

    • (左选右不选择,左边的元素存在,即$i \in [\left \lfloor \frac{k}{2} \right \rfloor , \left \lfloor \frac{n+1}{2} \right \rfloor+ \left \lfloor \frac{k}{2} \right \rfloor]$)

       $ f[i+1][0][k?k+1:0]+=f[i][j][k]$ , 若原来没有或者没有拐弯,那么现在也不会有。

  • (左不选右选,右边的元素存在,即$i \in [1,\left \lfloor \frac{n}{2}  \right \rfloor )$)

       $f[i+1][j+1][0]+=f[i][j][w]$ 

  • (既选择左,又选择右侧元素,左右元素同时存在,上述两个集合的交集)

$f[i+1][j+1][max(w+1,j+2)]+=f[i][j][w]$ , 左侧的状态有两条路来走,我们取较大的一条。

上述DP细节较多,可以采用刷表实现,复杂度会是$O(n^3)$. 

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=305,mo=998244353;
int n,k;
namespace Subtask1 {int f[N][N][N];void main() {f[0][0][0] = 1;for (int i=0;i<(n+1)/2+k/2;i++)for (int j=0;j<=n;j++)for (int w = 0 ; w <= k+1 ; w++) {(f[i+1][0][0]+=f[i][j][w])%=mo;if (i>=(k/2)) (f[i+1][0][w?w+1:0]+=f[i][j][w])%=mo;if (i<n/2) (f[i+1][j+1][0]+=f[i][j][w])%=mo;if (i>=(k/2) && i<(n/2)) (f[i+1][j+1][max(w+1,j+2)]+=f[i][j][w])%=mo;}int ans = 0;for (int j=0;j<=n;j++)for (int w=0;w<=k+1;w++)(ans+=f[(n+1)/2+k/2][j][w])%=mo;cout<<ans<<'\n';exit(0);}
}
namespace Subtask2 {int f[N][N];int g(int n,int m) {memset(f,0,sizeof(f)); f[0][0] = 1;for (int i=0;i<=n;i++)for (int j=0;j<=m;j++) {f[i+1][0]=(f[i+1][0]+f[i][j])%mo;if (j+1<=m) f[i+1][j+1]=(f[i+1][j+1]+f[i][j])%mo;}int ret=0;for (int i=0;i<=m;i++) ret=(ret+f[n][i])%mo;return ret % mo;}void main() {int ans = 1ll * g((int)ceil((double)n/2.0),k/2) * g(n/2,k/2) % mo;cout<<ans<<'\n';exit(0);}
}
signed main() {cin>>n>>k;if (k&1) Subtask1::main();else Subtask2::main();return 0;
}

B.cpp

 Problem C      

  维护序列$a_i$支持$q$次查询操作,形如$l,r,d$表示在区间$[l,r]$中是$d$倍数的数的个数。

  对于$100\%$的数据满足$n,q,a_i \leq 10^5$

  Solution : 直接暴力分块,每一块中维护这个块内约数为$i , i \in [1,10^5]$的数的个数,方便$O(1)$查询。

       对于块外元素,直接暴力,对于块内元素,直接跑块即可。

       时空复杂度都是$O(n \sqrt{n})$  。

# pragma GCC optimize(3)
# include <bits/stdc++.h>
# define Rint register int
using namespace std;
const int N=1e5+1;
struct rec{int l,r,cnt[N];
}tr[318];
int n,m,a[N],blong[N],block,num;
inline int read()
{int X=0; char c=0;while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();return X;
}
void write(Rint x) {if (x>9) write(x/10);putchar('0'+x%10);
}
inline void writeln(Rint x) {write(x); putchar('\n');
}
int query(int l,int r,int d)
{int ret = 0;if (blong[l] == blong[r]) {for (Rint i=l;i<=r;i++)if (a[i]%d == 0) ret++;return ret; }for (Rint i=l;i<=tr[blong[l]].r;i++) if (a[i]%d == 0) ret++;for (Rint i=tr[blong[r]].l;i<=r;i++) if (a[i]%d == 0) ret++;for (Rint i = blong[l]+1 ; i<=blong[r]-1; i++) if (d<=n) ret+=tr[i].cnt[d];return ret;
}
int main()
{n = read(); m =read();for (Rint i=1;i<=n;i++) a[i]=read();block=sqrt(n); num=n/block; if (n%block) num++;for (Rint i=1;i<=num;i++) {tr[i].l=(i-1)*block+1,tr[i].r=i*block;}tr[num].r=n;for (Rint i=1;i<=n;i++) {blong[i]=(i-1)/block+1;for (Rint j=1;j<=sqrt(a[i]);j++) {if (a[i]%j!=0) continue; tr[blong[i]].cnt[j]++; if (j*j!=a[i]) tr[blong[i]].cnt[a[i]/j]++;} }int l,r,d;while (m--) {l = read(),r =read(),d=read(); query(l,r,d);writeln(query(l,r,d));}return 0;
}

C.cpp

转载于:https://www.cnblogs.com/ljc20020730/p/11391007.html

HGOI 20190821 慈溪一中互测相关推荐

  1. P6271 [湖北省队互测2014]一个人的数论(莫比乌斯反演,拉格朗日插值)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 P6271 [湖北省队互测2014]一个人的数论(莫比乌斯反演,拉格朗日插值) Problem Sol ...

  2. P6271 [湖北省队互测2014]一个人的数论(莫比乌斯反演 + 伯努利数)

    P6271 [湖北省队互测2014]一个人的数论 ∑i=1nim[gcd⁡(i,n)=1]∑d∣nμ(d)dm∑i=1ndim由伯努利数可知∑i=0nim=1m+1∑i=0mCm+1iBi(n+1)m ...

  3. UOJ#191. 【集训队互测2016】Unknown

    UOJ#191. [集训队互测2016]Unknown 题目描述 Solution 二进制分组. 每一个组内维护一个斜率单调减的凸包. 因为有删点,避免出现反复横跳产生的爆炸复杂度,需要等到同一深度的 ...

  4. [2015国家集训队互测]口胡

    比赛链接 http://uoj.ac/contest/11 口胡题解 A.[集训队互测2015]Robot 直接果断打暴力了...这个暴力很好写,我就不废话了 B.[集训队互测2015]Marketi ...

  5. 2017.10.24队内互测——压轴出场的互测终曲|(*_-)

    出题人: Sherlock, Frank, WWQ, MurasameKatana 终于到了我们组出题啦. 题面都是我自己写的2333 Problem 1 :令咒 题目来源:http://codevs ...

  6. 2017.9.16队内互测——老年组Day1

    2017.9.16队内互测--老年组Day1 出题人:feather,MeiCo,Summer,Black Problem 1: 对于100%的数据,n<=1000 截图比较奇怪-还请见谅 简单 ...

  7. 【LOJ3077】「2019 集训队互测 Day 4」绝目编诗

    [题目链接] 点击打开链接 [思路要点] 不难发现各个边双连通分量可以分开处理,桥边可以直接删除. 可以证明,对于每一个边双连通分量,当 M−NM-NM−N 超过 O(N)O(\sqrt{N})O(N ...

  8. 「2019 集训队互测 Day 1」最短路径 解题报告

    一.题目概述 题目链接:Libre OJ. 给出一张图,求出 ans=∑i=1n∑j=1n[i≠j]dk(i,j)ans=\sum_{i=1}^n\sum_{j=1}^n[i\ne j]\texttt ...

  9. EZ 2018 05 06 NOIP2018 慈溪中学集训队互测(五)

    享受爆零的快感 老叶本来是让初三的打的,然后我SB的去凑热闹了 TM的T2写炸了(去你妹的优化),T1连-1的分都忘记判了,T3理所当然的不会 光荣革命啊! T1 思维图论题,CHJ dalao给出了 ...

最新文章

  1. oracle数据库性能awr,常见问题:如何使用AWR报告来诊断数据库性能问题
  2. Spring中ThreadPoolTaskExecutor的线程调度及问题
  3. Python的GIL是什么鬼,多线程性能究竟如何
  4. Java编程基础-变量
  5. “猜你喜欢” — 浅谈内容分发中的推荐系统
  6. dockerfile php环境变量,docker - 在Dockerfile中,如何更新PATH环境变量?
  7. Microsoft.TeamFoundation.VersionControl.Client.dll的位置
  8. SAP CRM WebClient UI calculated fields的工作原理
  9. 旷视科技Face++进军机器人业务
  10. TypeScript_学习笔记
  11. COCOS2D游戏适配IPAD RETINA
  12. 项目中的常量是放在接口里还是放在类里呢?
  13. TDDL分布式数据库
  14. 基于Java的Minecraft游戏后端自定义插件 08VexView界面绘制与按钮和扩展VexView事件使用
  15. HTML5期末大作业:蘑菇街网站设计——2021蘑菇街首页(1页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web期末作业设计网页_清新淡雅蘑菇街大学生网页设计作业成品
  16. 常见的27个电源符号
  17. FileZilla FTP Server 安全加固
  18. Python_美多商城(验证码)_3
  19. 派森python_python2.7下载-派森(Python)下载v2.7.18 官方正式版【x86|x64】-西西软件下载...
  20. Linux proxy 设置

热门文章

  1. 使用WHM重新编译Apache+PHP环境
  2. 果汁机器人传销_【调查】“洋果汁治百病”?然健环球涉嫌传销大起底
  3. linux定时删除或者压缩日志文件
  4. BCIduino转载|3D打印机使用的日常问题汇总
  5. 深入理解JavaScript箭头函数
  6. kafka报错:The Cluster ID doesn‘t match stored clusterId Some in meta.properties
  7. java实现i18n国际化
  8. HttpWebRequest 无法连接到远程服务器
  9. win10台式机插入耳机检测不出来
  10. 双下划线一粗一细怎么加_为什么下划线粗细不一样