AGC003[BCDEF]题解
2018-12-28 有点累EF明天再写叭=v=
2018-12-29 update EF
B - Simplified mahjong
可以注意到 一段连续的非0序列都可以凑出
就是显然%2=0的可以内部配完 然后%2=1的可以随便向两边传递这个1(就是和旁边的配对改变自己和配对的奇偶性从而使自己变成%2=0旁边变成%2=1)于是就按照0分割统计答案就行了qwq
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 20021225
#define ll long long
#define mxn 100010
using namespace std;
ll a[mxn],n;
int main()
{
scanf("%lld",&n);ll ans=0;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
{
ll cnt=a[i];
while(i<n && a[i+1]!=0) cnt+=a[i+1],i++;
ans+=cnt/2;
}
printf("%lld\n",ans);
return 0;
}
C - BBuBBBlesort!
两种操作 翻转长度为2 翻转长度为3
我们用dis[i]表示排名第i的和它所在的初始的位置的距离
翻转长度为2的可以改变一对的奇偶性 然后长度为3的不改变奇偶性
然后把奇数的个数加起来/2就好啦=v=
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 20021225
#define ll long long
#define mxn 100100
using namespace std;
int a[mxn],n,id[mxn];
bool cmp(int x,int y)
{
return a[x]<a[y];
}
int main()
{
scanf("%d",&n);ll ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),id[i]=i;
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++) ans+=abs(id[i]-i)&1;
printf("%lld\n",ans/2);
return 0;
}
D - Anticube
我再读错题我就是彪头[flag] = =
读成了选择一段区间 然后思考一下午不会做= =
看题解发现md是随便选几个
这样的话就每个数质因数分解 然后指数全部%3变成最小表示 求一下他的补集 就是 所有指数变成(3-x)%3
这样的话贪心选 自己或补集就可以辣 注意补集=自己只能选一个
发现 ai 10e10 (上pollard-rho啊)
我们可以筛一下10e10的1/3次方以内的质数 然后分解一下
剩下的一定是一个大质数的平方或者大质数
直接判一下就好了=v=
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define inf 20021225
#define ll long long
#define mxn 100100
using namespace std;
map<ll,int> s;
map<ll,bool> h;
bool isp[10100];
ll p[1310],cnt;
void get(int n)
{
isp[1]=1;
for(int i=2;i<=n;i++)
{
if(!isp[i]) p[++cnt]=i;
for(int j=1;j<=cnt&&p[j]*i<=n;j++)
{
isp[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
}
ll a[mxn],b[mxn]; int n;
int main()
{
get(10000);// printf("%d\n",cnt);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
ll q=a[i]; a[i]=b[i]=1ll;
for(int j=1;j<=cnt;j++)
{
int qwq=0;
if(q==1) break;
if(q%p[j]==0)
{
while(q%p[j]==0)
{
q/=p[j];
qwq++;
}
qwq%=3;
if(qwq==1) b[i]*=(ll)p[j]*p[j],a[i]*=p[j];
if(qwq==2) b[i]*=p[j],a[i]*=(ll)p[j]*p[j];
}
}
if(q!=1)
{
ll x=(ll)sqrt(q);
if(x*x == q) b[i]*=x,a[i]*=x*x;
else b[i]*=q*q,a[i]*=q;
}
}
for(int i=1;i<=n;i++) s[a[i]]++;
int ans=0;// printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
if(!h[a[i]])
{
h[a[i]]=h[b[i]]=1;
if(a[i]==b[i]) ans++;
else ans+=max(s[a[i]],s[b[i]]);
}
}
printf("%d\n",ans);
return 0;
}
EF明天更!(两道神题想起来写起来都很烦= =)
E - Sequential operations on Sequence
神仙题做不来
首先可以得到一个结论 a[i]>=a[i+1]的时候只有a[i+1]是有用的 那么我们可以通过单调栈来维护就可以剔除掉没有用的部分
接下来我们来讲神仙操作
我们将操作序列倒过来 倒着进行推导
首先 令s = a[i+1] / a[i] 那么所有的数一定是有一个s倍的增加 然后 r=a[i+1]%a[i] 就是前r个会多出一个零头
对于维护 我们利用两个数组 add 和 mul 分别维护个体增长和倍数级的增长
那么我们可以通过递归来实现 solve(s,l) -> solve(s%st[pos],l*s/st[pos]) 来表示零头和倍数级
那么我们可以通过二分来找到第一个<s的st[pos]那么就可以将这个过程优化到log
然后注意到s每次%一个小于s的数 这样的话最多只会进行log次[类似辗转相除]
这样的话 我们对于一次处理的复杂度是O(lgslgn)
一共n次操作 就是O(nlgnlgs)啦
然后处理的时候 add 是对于每一个位置的一个差分数组 那么最后就是要前缀和啦 mul就是对于每一次操作的每一个位置增长的倍数数组 那么第一次的倍数数组当然是 mul[1] 啦
由于第一次 每一个位置 对应的都是i 每一个数只出现一次 所以就是mul整体 add就是前缀和
最后就是 add的前缀和 + mul[1] 就是答案咯
代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 20021225
#define ll long long
#define mxn 100010
using namespace std;
ll a[mxn],stk[mxn];int tp,n,q;
ll cnt[mxn],add[mxn],mul[mxn];
int erf(int l,int r,ll x)
{
int pos=r;
while(l<=r)
{
int mid=l+r>>1;
if(stk[mid] <= x) pos=mid,l=mid+1;
else r=mid-1;
}
return pos;
}
void work(ll l,ll k,int x)
{
if(!k) return;
if(k<=stk[1])
{
add[1] += l;
add[k+1] -= l;
return;
}
int pos=erf(1,x,k);
ll tmp = k / stk[pos];
mul[pos] += tmp*l;
work(l,k%stk[pos],pos-1);
}
int main()
{
scanf("%d%d",&n,&q);
stk[++tp] = n;
for(int i=1;i<=q;i++)
{
scanf("%lld",&a[i]);
while(tp && stk[tp] >= a[i]) tp--;
stk[++tp] = a[i];
}
mul[tp] = 1;
for(int i=tp;i>=2;i--)
{
ll tmp = stk[i]/stk[i-1];
ll fin = stk[i]%stk[i-1];
mul[i-1] += mul[i]*tmp;
work(mul[i],fin,i-1);
}
for(int i=1;i<=stk[1];i++)
{
add[i] += add[i-1];
printf("%lld\n",mul[1]+add[i]);
}
for(int i=stk[1]+1;i<=n;i++)
printf("0\n");
return 0;
}
F在路上了qwq
F - Fraction of Fractal
非常nb的一个题qwq(才不会说我题意理解了半天= =题意不理解的可以去loj看中文题面会好很多= =)
看了题解才会做 简直是神仙
我们对于一行(或一列)的两端都是黑色的计数分别为 lr ud 对所有的黑色格子计数为cnt
然后会出现4种情况
1.lr>0&&ud>0 这个时候必定是全部联通的 因为原图中保证了四联通 而每一个格子和上下左右是都能联通的 答案是1
2.lr=0&&ud=0 这个时候必定是全部不连通 所以答案是 cnt^(k-1)
3.lr>0&&ud=0 4.lr=0&&ud>0
这两种情况是等价的 因为我们可以把其中一个旋转45°来转换成另一种情况=v=
我们在这里只讨论 ud>0
ud>0那么就是整个图形会有一些上下联通的块把它们连接起来 整个图形就是由一些链组成的
这样的时候我们怎么计数呢?
显然 链是树 所以我们可以根据森林的性质 树数=点数-边数
这样的话我们只需要分开统计链和点就可以了
点很好计数 每次一个黑色格子变成一个黑色联通块 是指数级增长的 就是cnt^(k-1)
边怎么统计呢 这就用到神仙做法了
我们再来统计一个上下接口 就是(a[i-1][j]和a[i][j])都是黑色的情况 计数为eud 这个时候它们之间是会有一条边的
然后我们可以列出柿子 Ek = Ek-1 * cnt + eud*ud^(k-2) 边界条件就是E2=eud
因为 每一个k-1分形里都有ud^(k-2)个联通的1阶分形然后*eud条新边就可以了=v=
然后这个东西构造一波矩阵乘法就可以了w
注意边界数据 k=0 ans=1 = =
代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 20021225
#define ll long long
#define mdn 1000000007
using namespace std;
struct matrix{int a[3][3],n;};
inline void init(matrix &a)
{
memset(a.a,0,sizeof(a.a));
}
matrix operator *(matrix a,matrix b)
{
matrix tmp; init(tmp); tmp.n=a.n;
//printf("%d\n",tmp.a[2][2]);
for(int i=1;i<=a.n;i++)
for(int j=1;j<=a.n;j++)
for(int k=1;k<=a.n;k++)
tmp.a[i][j] = ((ll)tmp.a[i][j] +(ll)a.a[i][k]*b.a[k][j]%mdn)%mdn;
return tmp;
}
matrix ksm(matrix bs,ll mi)
{
matrix tmp; tmp.n=bs.n; init(tmp);
for(int i=1;i<=tmp.n;i++) tmp.a[i][i]=1;
while(mi)
{
if(mi&1) tmp=tmp*bs;
bs=bs*bs; mi>>=1;
}
return tmp;
}
char mp[1100][1100];
int ud,lr,eud,elr,cnt;
int ksm(int bs,ll mi)
{
int ans=1;
while(mi)
{
if(mi&1) ans=(ll)ans*bs%mdn;
bs=(ll)bs*bs%mdn; mi>>=1;
}
return ans;
}
int main()
{
int h,w;ll k;
scanf("%d%d%lld",&h,&w,&k);
if(k<=1){printf("1\n");return 0;}
for(int i=1;i<=h;i++)
{
scanf("%s",mp[i]+1);
if(mp[i][1] == mp[i][w] && mp[i][1] =='#') lr++;
for(int j=2;j<=w;j++) if(mp[i][j] == mp[i][j-1] && mp[i][j] == '#') elr++;
}
for(int i=2;i<=h;i++)
for(int j=1;j<=w;j++) if(mp[i-1][j] == mp[i][j] && mp[i][j] == '#') eud++;
for(int i=1;i<=w;i++) if(mp[1][i] == mp[h][i] && mp[h][i] == '#') ud++;
for(int i=1;i<=h;i++) for(int j=1;j<=w;j++) cnt+=(mp[i][j]=='#');
if(lr && ud)
{
printf("1\n"); return 0;
}
if(!lr && !ud)
{
printf("%d\n",ksm(cnt,k-1)); return 0;
}
//printf("QAQ");
if(lr) swap(lr,ud),swap(elr,eud); // only ud
matrix ans; ans.n = 2;// printf("%d %d\n",eud,ud);
ans.a[1][1] = cnt; ans.a[1][2] = 0; ans.a[2][1] = 1; ans.a[2][2] = ud;
ans = ksm(ans,k-2);
int fin =(ll)ans.a[1][1]*eud%mdn + (ll)ud*eud%mdn*ans.a[2][1]%mdn;
fin%=mdn; int mis = ksm(cnt,k-1);// printf("%d\n",mis);
//printf("%d %d %d %d\n",ans.a[1][1],ans.a[1][2],ans.a[2][1],ans.a[2][2]);
printf("%d\n",(mis-fin+mdn)%mdn);
return 0;
}
AGC003[BCDEF]题解的更多相关文章
- AGC002[BCDEF]题解
F是计数于是就做(kan ti jie)了= = B - Box and Ball 模拟一下 每个盒子开一个d表示有的球数 可能存在红球的打个标记 传递一下就行了 #include<cstdio ...
- AtCoder AGC003 简要题解
A 首先横向和纵向互相独立,因此只考虑横向的情况. 那么显然只要不只往一边走都一定存在一种构造方式,直接判断即可,复杂度 \(\mathcal{O}(|S|)\). B 首先相邻两个数同时配对两次可以 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
随机推荐
- python中用os.walk查找全部的子文件
import os import shutil # 要遍历查找的文件所在的父文件夹 trajectory_filename =r"D:\mapping" # 要粘贴到的目标文件夹 ...
- 第九届ECNU Coder A.足球锦标赛
题目链接:http://acm.ecnu.edu.cn/contest/16/problem/A/ 题目: A. 足球锦标赛 Time limit per test: 2.0 seconds Time ...
- React Hooks简单业务场景实战(非源码解读)
前言 React Hooks 是React 16.7.0-alpha 版本推出的新特性.从 16.8.0 开始,React更稳定的支持了这一新特性. 它可以让你在不编写 class 的情况下使用 st ...
- windows 命令端口映射
显示映射列表netsh interface portproxy show all 将本地的1234端口的数据转发至192.168.x.x上的1234端口netsh interface portprox ...
- python通过post提交数据的方法
python通过post提交数据的方法 本文实例讲述了python通过post提交数据的方法.分享给大家供大家参考. 具体实现方法如下: # -*- coding: cp936 -*- imp ...
- python安装centos7
1.安装git (需root权限) yum -y install git 2.安装依赖包 yum -y install gcc make patch gdbm-devel openssl-devel ...
- sessionStorage、localStorage与cookie
sessionStoage:容量大.安全.临时存储,跨页面 localStorage: 容量大.安全.永久存储.跨页面 应用: <!-- 存储页面 test-local --> <t ...
- JavaScript 高级程序设计(第3版)第一章 (js简介)
1.我比js早一年 2.web浏览器是ECMAScript实现的宿主环境之一. 其它实现ECMAScript的宿主环境包括Node和Adobe Flash 3.ECMAScript主要规定js的组成部 ...
- 高德地图POI采集(URL-API)
新手从零学起,成功跑通,记一下,技术大神们多多指点. ———————————————— 1-概述 POI:兴趣点.对于百度.高德等电子地图来说,一个POI是地图上的一个店铺/商场/小区等等. 这次要解 ...
- Netty核心组件介绍及手写简易版Tomcat
Netty是什么: 异步事件驱动框架,用于快速开发高i性能服务端和客户端 封装了JDK底层BIO和NIO模型,提供高度可用的API 自带编码解码器解决拆包粘包问题,用户只用关心业务逻辑 精心设计的Re ...