[Atcoder Grand Contest 003] Tutorial
Link:
A:
判断如果一个方向有,其相反方向有没有即可
#include <bits/stdc++.h> using namespace std;
char s[];
map<char,bool> mp;
int main()
{
scanf("%s",s);
for(int i=;i<strlen(s);i++) mp[s[i]]=true;
if(mp['S']==mp['N']&&mp['E']==mp['W']) puts("Yes");
else puts("No");
return ;
}
Problem A
B:
贪心最大化利用即可
#include <bits/stdc++.h> using namespace std;
int n,dat[];
long long res=;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&dat[i]);
for(int i=;i<=n-;i++)
{
res+=dat[i]/;dat[i]%=;
if(dat[i+]>dat[i]) dat[i+]-=dat[i],res+=dat[i];
}
res+=dat[n]/;
printf("%lld",res);
return ;
}
Problem B
C:
可以将两个操作转换为:
1、交换两个相邻的数
2、交换两个中间相间一个的数
由于只要求操作1的最小数,可以发现调整好所有数的序号的奇偶性就能用操作2完成任务
因此求出原序号为奇数,排序后序号为偶数的数的个数即可(原偶现奇的个数与其相同)
#include <bits/stdc++.h> using namespace std;
int n,dat[],id[]; bool cmp(int a,int b)
{return dat[a]<dat[b];}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&dat[i]),id[i]=i;
sort(id+,id+n+,cmp);
int res=;
for(int i=;i<=n;i++)
if((id[i]&)&&!(i&)) res++;
printf("%d",res);
return ;
}
Problem C
D:
思路类似于 [Codeforces#480 D] ,只不过将平方改成了立方
要判断两个数的积为立方,可以将每个数的各个质因数次幂$mod 3$化简后再判断
于是我们求出每个数化简后的结果,统计出现次数,同时求出化简后的数的补数
最后在一个数及其补数中选择个数更多的那一组即可(特判:如果化简后为1只能算一个)
实现的难点在质因数分解……
由于$n\le 10^{10}$,肯定不能求出$n$以内的所有质数
于是要先将$10^{\frac{10}{3}}$内的质因数分解掉,保证剩下的质因数的次幂不会超过2次
实际上,剩下的数只有3种情况,分类讨论就好了:
1、$p^2$ 2、$p$ 3、$p*q$ ($p,q$为质数)
这样就能在$O(1)$的时间内计算大于$10^{\frac{10}{3}}$的质因数的化简结果及其补数了
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const int MAXN=1e5+;
int n,pri[],vis[],tot,res=;
ll x[MAXN],y[MAXN],t;
map<ll,int> mp,avl; ll cube(int a){return 1ll*a*a*a;}
ll sqr(int a){return 1ll*a*a;}
int main()
{
for(int i=;i<=;i++)
{
if(!vis[i]) pri[++tot]=i;
for(int j=;j<=tot&&i*pri[j]<=;j++)
{
vis[i*pri[j]]=;
if(i%pri[j]==) break;
}
} scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%lld",&t);x[i]=y[i]=;
for(int j=;cube(pri[j])<=t;j++)
{
int cnt=;
while(t%pri[j]==) t/=pri[j],cnt++;
if(cnt%==) x[i]*=pri[j],y[i]*=sqr(pri[j]);
else if(cnt%==) x[i]*=sqr(pri[j]),y[i]*=pri[j];
}
x[i]*=t;mp[x[i]]++;
y[i]*=sqr(sqrt(t))==t?sqrt(t):sqr(t);
} for(int i=;i<=n;i++)
if(!avl[x[i]])
{
avl[x[i]]=avl[y[i]]=;
if(x[i]==) res++;
else res+=max(mp[x[i]],mp[y[i]]);
}
printf("%d",res);
return ;
}
Problem D
如果操作为除法/取模,且要枚举$n$个除数/模数时,
学会较小数暴力,较大数分类讨论的方式(如 [ARC060 D])
E:
首先可以将$dat$序列改为单调递增的,其他项明显是多余的
通过观察发现每一项可以由之前的项重复、组合而成(可能留有小于$len[1]$的后缀)
于是我们令$cnt[i]$为第$i$项被重复的总次数,对于从后往前每一个$i$:
每次二分找到最大的小于$dat[i]$的$dat[j]$,那么第$j$项可以多重复$dat[i]/dat[j]*cnt[i]$次
接下来将$dat[i]$mod$dat[j]$,寻找下一个重复项
由于一个数$mod$比自己小的数明显最多进行$log(n)$次,因此复杂度为$O(n*log(n))$
由于每项在整块整块分解后仍可能有小于$len[1]$的后缀,需要另外统计
为了保证时间复杂度,且由于该后缀一定连续,因此差分统计就好了
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const int MAXN=1e5+;
int n,q,tot;
ll res[MAXN],dat[MAXN],cnt[MAXN]; int Query(ll x,int r)
{
int ret=-,l=;
while(l<=r)
{
int mid=(l+r)>>;
if(dat[mid]<=x) ret=mid,l=mid+;
else r=mid-;
}
return ret;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=q;i++) scanf("%lld",&dat[i]);
dat[]=n;//如果最小值大于n要添加n
for(int i=;i<=q;i++)
{
while(tot>=&&dat[i]<dat[tot]) tot--;
dat[++tot]=dat[i];
} cnt[tot]=;
for(int i=tot;i>=;i--)
{
ll k=dat[i],pos=Query(k,i-);
while(pos>=)
{
cnt[pos]+=(k/dat[pos])*cnt[i];
k=k%dat[pos];pos=Query(k,pos-);
}
res[]+=cnt[i];res[k+]-=cnt[i];
}
for(int i=;i<=n;i++)
res[i]+=res[i-],printf("%lld\n",res[i]);
return ;
}
Problem E
F:
%%%LCA的题解:https://loj.ac/article/189
一眼看上去完全不可做的题(好像对我而言所有题都这样)
但先进行大的分类后其实会发现明朗很多
令矩阵中有色点数为$cnt$,上下/左右相邻的有色点对数分别为$pv,ph$
令原矩阵上下/左右拼接后能连通的列数/行数分别为$sv,sh$
1、如果$sv,sh$都大于零,明显全部连通
2、如果$sv,sh$都为零,明显答案为$cnt^{k-1}$
3、如果$sv,sh$中恰有一个大于零,需要递推:
将最终矩阵中每一个初始矩阵视为一个点,两点相连通则视为有一条边
由于最终状态不可能有环,求连通块的个数,其实就是求点数与边数的差
根据上面求出的量,可以写出如下的递推式:
$V_k=V_{k-1}*cnt$
$E_k=E_{k-1}*cnt+pv(h)*sv(h)$
对于这样的式子矩乘优化就好了
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const int MOD=1e9+,MAXN=;
struct matrix
{
ll p[][];
matrix(){memset(p,,sizeof(p));}
void init(){p[][]=p[][]=;}
friend matrix operator * (const matrix &a,const matrix &b)
{
matrix ret;
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
(ret.p[i][j]+=a.p[i][k]*b.p[k][j]%MOD)%=MOD;
return ret;
}
friend matrix quick_pow(matrix a,ll b)
{
matrix ret;ret.init();
for(;b;b>>=,a=a*a)
if(b&) ret=ret*a;
return ret;
}
}; char s[MAXN][MAXN];
ll k;
int n,m,cnt,pv,ph,sv,sh;
ll quick_pow(ll a,ll b)
{
ll ret=;
for(;b;b>>=,a=a*a%MOD)
if(b&) ret=ret*a%MOD;
return ret;
} int main()
{
scanf("%d%d%lld",&n,&m,&k);
if(k<=) return puts(""),;
for(int i=;i<=n;i++) scanf("%s",s[i]+);
for(int i=;i<=n;i++) for(int j=;j<=m;j++)
if(s[i][j]=='#')
{
cnt++;
pv+=(s[i][j]==s[i+][j]);
ph+=(s[i][j]==s[i][j+]);
}
for(int i=;i<=m;i++) sv+=(s[][i]=='#'&&s[n][i]=='#');
for(int i=;i<=n;i++) sh+=(s[i][]=='#'&&s[i][m]=='#'); if(sv&&sh) return puts(""),;
else if(!sv&&!sh) return printf("%lld",quick_pow(cnt,k-)),;
else
{
matrix t;t.p[][]=cnt;t.p[][]=(sv?pv:)+(sh?ph:);t.p[][]=sv+sh;
t=quick_pow(t,k-);printf("%lld",(t.p[][]-t.p[][]+MOD)%MOD);
}
return ;
}
Problem F
[Atcoder Grand Contest 003] Tutorial的更多相关文章
- AtCoder Grand Contest 003
AtCoder Grand Contest 003 A - Wanna go back home 翻译 告诉你一个人每天向哪个方向走,你可以自定义他每天走的距离,问它能否在最后一天结束之后回到起点. ...
- AtCoder Grand Contest 003 D - Anticube
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_d 题目大意: 给定\(n\)个数\(s_i\),要求从中选出尽可能多的数,满足任意两个数之积 ...
- AtCoder Grand Contest 003 E - Sequential operations on Sequence
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_e 题目大意 一串数,初始为\(1\sim N\),现有\(Q\)个操作,每次操作会把数组长度 ...
- AtCoder Grand Contest 003 F - Fraction of Fractal
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_f 题目大意: 给定一个\(H×W\)的黑白网格,保证黑格四连通且至少有一个黑格 定义分形如下 ...
- [Atcoder Grand Contest 004] Tutorial
Link: AGC004 传送门 A: …… #include <bits/stdc++.h> using namespace std; long long a,b,c; int main ...
- Atcoder Grand Contest 003 F - Fraction of Fractal(矩阵乘法)
Atcoder 题面传送门 & 洛谷题面传送门 Yet another AGC F,然鹅这次就没能自己想出来了-- 首先需注意到题目中有一个条件叫做"黑格子组成的连通块是四联通的&q ...
- [Atcoder Grand Contest 002] Tutorial
Link: AGC002 传送门 A: …… #include <bits/stdc++.h> using namespace std; int a,b; int main() { sca ...
- [Atcoder Grand Contest 001] Tutorial
Link: AGC001 传送门 A: …… #include <bits/stdc++.h> using namespace std; ; ]; int main() { scanf(& ...
- AtCoder Grand Contest 003题解
传送门 \(A\) 咕咕 const int N=1005; char s[N];int val[N],n; int main(){ scanf("%s",s+1),n=strle ...
随机推荐
- 写一个JavaScript“返回顶部”功能
在web页面中,如果页面较高,为了方便用户快速地返回顶部,都会添加一个返回顶部按钮. 效果演示可以查看本页.如果页面有滚动高度,右下角就会有一个含有“返回顶部”字样的黑色背景半透明的小条条.点击这里“ ...
- MySQL使用笔记(六)条件数据记录查询
By francis_hao Dec 17,2016 条件数据记录查询 mysql> select field1,field2-- from table_name where 条件; 其中 ...
- [lucene系列笔记3]用socket把lucene做成一个web服务
上一篇介绍了用lucene建立索引和搜索,但是那些都只是在本机上运行的,如果希望在服务器上做成web服务该怎么办呢? 一个有效的方法就是用socket通信,这样可以实现后端与前端的独立,也就是不管前端 ...
- istringstream()函数的用法
istringstream()函数的用法 头文件:#include 功能:将一个含有多个空格的字符串分割开来 eg:
- SpringMVC学习 -- 使用 @RequestMapping 映射请求
在控制器的类定义及方法出定义出都可以标注 @RequestMapping: 类定义处:提供初步的请求映射信息.相对于 Web 应用的根目录. 方法定义出:提供进一步的细分映射信息.相对于类定义处的 U ...
- event loop 小记
水平不够,只能整理一下知乎大神的回答,勉强度日这样子 在一个事件循环里,会有两个主要的队列:task queue 和 micro-task quene. 其中 task 包括: script(整体代码 ...
- javaScript中的this关键字解析
this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要.接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示, ...
- Fragment里使用 PhoneGap 的 CordovaWebView
首先说明一下为什么要使用 CordovaWebView 而不直接使用 WebView 呢?由于 Android4.4 版本之后对 WebView 做了很大的改变,具体参考 这篇文章:理解WebKit和 ...
- java 线程 join(wait) 后,是如何唤醒
概要:锁是线程,锁对象执行完毕后,会调用自身对象上的notify(); Join 方法:本质上还是根据wait方法实现的.分析join源码发现join方法本身是使用了synchronized修饰符的. ...
- Spring MVC框架下 从后台读取数据库并显示在前台页面【笔记自用 不推荐作为参考】
1.书写jsp页面 people.jsp 1.设计显示格式以及内容显示 2.设计显示内容的范围 2.书写entity实体类 PeopleFormMap.java 书写传入的参数主要包括 要引用的数据 ...