好了做了SDOI day1的3道题,来讲下做法及感想吧

T1:排序(暴力,搜索)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3990

我们可以很轻易的发现,对于一个操作方案,交换两个操作顺序不会影响答案,因此我们可以从小到大枚举答案,可以发现,对于第i种操作过后,每个2^i的块必须是连续的

那么在第i种操作之前,最多只能有2个块不连续,那么如果没有块不连续,不用执行该种操作;只有一个块不连续,交换这个块的两小块;两个块分4种情况讨论,用dfs暴力搜索即可

时间复杂度看上去是O(4^N),但好像可以证出复杂度其实是O(2^NlogN)N=20都能跑过

CODE:

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 5000
int a[maxn],n,f[];
long long ans=;
inline void _swap(int *a,int *b,int step) {
for (int i=;i<=step;i++) swap(a[i],b[i]);
}
inline bool check(int x,int y) {return a[x+y]+==a[x+y+];}
int dfs(int x,int y) {
if (x==n+) return ans+=f[y];
int w[],cnt=;
int step=<<(x-);
for (int i=;i<<<n;i+=<<x) {
if (!check(i,step)) w[++cnt]=i;
if (cnt>) return ;
}
if (cnt==) dfs(x+,y);
if (cnt==) {
_swap(a+w[],a+w[]+step,step);
if (check(w[],step)) dfs(x+,y+);
_swap(a+w[],a+w[]+step,step);
}
if (cnt==) {
int *l1=a+w[],*l2=a+w[],*r1=a+w[]+step,*r2=a+w[]+step;
_swap(l1,l2,step);
if (check(w[],step)&&check(w[],step)) dfs(x+,y+);
_swap(l1,l2,step);
_swap(l1,r2,step);
if (check(w[],step)&&check(w[],step)) dfs(x+,y+);
_swap(l1,r2,step);
_swap(r1,l2,step);
if (check(w[],step)&&check(w[],step)) dfs(x+,y+);
_swap(r1,l2,step);
_swap(r1,r2,step);
if (check(w[],step)&&check(w[],step)) dfs(x+,y+);
_swap(r1,r2,step);
}
} int main(){
scanf("%d",&n);
f[]=;
for (int i=;i<=n;i++) f[i]=f[i-]*i;
for (int i=;i<=(<<n);i++) {
scanf("%d",a+i);
a[i]--;
}
dfs(,);
printf("%lld\n",ans);
return ;
}

T2:寻宝游戏(平衡树,dfn序)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3991

这道题真的想不出来啊= =

贴下同学的题解吧= =

大概就是这样子的,看上去还是非常的形象的,但我根本没想到啊QAQ

Code:

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
#define maxn 101000
#define maxk 23
struct edges{
int to,next,dist;
}edge[maxn*];
int q[maxn],f[maxn][maxk],g[maxn],dfn[maxn];
struct cmp{
bool operator ()(int x,int y) {return dfn[x]<dfn[y];}
};
set<int,cmp> ma;
int next[maxn],l;
inline void addedge(int x,int y,int z) {
edge[++l]=(edges){y,next[x],z};next[x]=l;
edge[++l]=(edges){x,next[y],z};next[y]=l;
}
int fa[maxn],dep[maxn],n,s[maxn];
ll dis[maxn];
inline void bfs(){
q[]=;
for (int l=,r=,u=q[];l<=r;u=q[++l]) {
f[u][]=fa[u];
for (int i=;i<maxk;i++) {
if (f[f[u][i-]][i-]==) break;
f[u][i]=f[f[u][i-]][i-];
}
for (int i=next[u];i;i=edge[i].next) {
if (edge[i].to==fa[u]) continue;
fa[edge[i].to]=u;dis[edge[i].to]=dis[u]+edge[i].dist;
dep[edge[i].to]=dep[u]+;
q[++r]=edge[i].to;
}
}
for (int i=n;i>;i--) {
int u=q[i];
s[u]++;s[fa[u]]+=s[u];
}
s[]++;
for (int i=;i<=n;i++) {
int u=q[i];
dfn[u]=g[fa[u]]+;
g[fa[u]]+=s[u];
g[u]=dfn[u];
}
}
inline int up(int x,int y) {
for (int i=;i<maxk;i++) if ((<<i)&y) x=f[x][i];
return x;
}
inline int lca(int x,int y) {
if (dep[x]<dep[y]) swap(x,y);
x=up(x,dep[x]-dep[y]);
if (x==y) return x;
for (int i=maxk-;i+;i--) {
if (f[x][i]==f[y][i]) continue;
x=f[x][i];y=f[y][i];
}
return f[x][];
}
inline ll getdist(int x,int y) {return dis[x]+dis[y]-dis[lca(x,y)]*;}
ll ans;
typedef set<int,cmp>::iterator iter;
inline void ins(int x) {
if (ma.size()==) {
ma.insert(x);return ;
}
if (ma.size()==) {
ans=getdist(x,*ma.begin());
ma.insert(x);
return ;
}
iter it=ma.lower_bound(x);
iter last=it;it--;
if (last!=ma.end()&&last!=ma.begin()) ans-=getdist(*it,*last);
if (last!=ma.begin()) ans+=getdist(*it,x);
if (last!=ma.end()) ans+=getdist(x,*last);
ma.insert(x);
}
inline void del(int x){
ma.erase(x);
if (ma.size()==) return ;
if (ma.size()==) {
ans=;return ;
}
iter it=ma.lower_bound(x);
iter last=it;it--;
if (last!=ma.end()&&last!=ma.begin()) ans+=getdist(*it,*last);
if (last!=ma.begin()) ans-=getdist(*it,x);
if (last!=ma.end()) ans-=getdist(x,*last);
}
bool b[maxn];
int main(){
int m;
scanf("%d%d",&n,&m);
for (int i=;i<n;i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
}
bfs();
for (int i=;i<=m;i++) {
int x;
scanf("%d",&x);
b[x]^=;
if (b[x]) ins(x);
else del(x);
if (ma.size()>=) printf("%lld\n",ans+getdist(*ma.begin(),*ma.rbegin()));
else printf("0\n");
}
return ;
}

T3:序列统计(FFT)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3992

这道题分明就是原题好不好= =

首先我们可以很容易的写出状态转移f[i][[j*a[k]]+=f[i-1][j];

30%的分数可用矩阵乘法优化

我们取下离散对数(就是mod m意义下的),然后这个方程就变成了f[i][ind[j]+ind[a[k]]]+=sigma(f[i-1][ind[j]*cnt[inda[k]])

可以发现变成了卷积形式了,好像可以用fft优化了

但发现n很大

借鉴一下矩阵乘法的优化,可以发现多项式乘法满足结合律,那么我们可以愉快的学习快速幂的形式,变成f0*cnt^n次方了

时间复杂度是 mlogm logn完美解决本题

还有一件事,求离散对数可以不用大步小步法,因为p很小,可以直接p^2求出来

顺便提下原题是lydcjj(greenclouds)的kpmcup#1中的T1(ORZ),除了取离散对数其他都一模一样的

要不是做了MX的组合数和看过云神的题,还真不一定做得出来

总结一下:

作为省选题,还是很不错的

思考复杂度都不低(虽然有人说3道都是原题QAQ,自己还是太弱)但是编程复杂度并不高,前两道都能秒,第3道套个fft模板也能秒

还是这种考思维的比较好玩,像陈老师这种业界毒瘤的数据结构题真是丧心病狂(づ ̄ 3 ̄)づ

Code:

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=;
#define maxn 80100
// template
inline int power(ll x,int y,int mod) {
ll t=;
for (;y;y>>=,(x*=x)%=mod)
if (y&) (t*=x)%=mod;
return t;
}
int w[maxn];
void fft(int *a,int n,int dep=) {
if (n==) return ;
static int tmp[maxn];
int mid=n>>;
fft(a,mid,dep+);fft(a+(<<dep),mid,dep+);
for (int i=;i<mid;i++) {
int s=a[(i<<)<<dep];
int t=a[(i<<|)<<dep]*1ll*w[i<<dep]%mod;
tmp[i]=(s+t)%mod;
tmp[i+mid]=(s-t)%mod;
}
for (int i=;i<n;i++) a[i<<dep]=tmp[i];
}
int fft_g=;
int N;
inline void fft_init(){
w[]=;
int step=power(fft_g,(mod-)/N,mod);
for (int i=;i<N-;i++) w[i+]=w[i]*1ll*step%mod;
}
int p;
bool isroot(int x) {
int sum=;
for (int i=;i<p-;i++) {
(sum*=x)%=p;
if (sum==) return ;
}
return ;
}
int n,X,S;
int ind[maxn];
int f[maxn],g[maxn],invN;
inline void prepare(){
scanf("%d%d%d%d",&n,&p,&X,&S);
int root=;
for (int i=;i<p&&!root;i++) if (isroot(i)) root=i; for (int i=,j=;i<p-;i++,(j*=root)%=p) ind[j]=i;
for (int i=;i<=S;i++) {
int x;
scanf("%d",&x);
if (x) g[ind[x]]=;
}
N=p<<;
while (N&(N-)) N++;
invN=power(N,mod-,mod);
fft_init();
}
inline void muil(int *x,int *g){
static int y[maxn];
for (int i=;i<N;i++) y[i]=g[i];
fft(x,N),fft(y,N);
for (int i=;i<N;i++) x[i]=x[i]*1ll*y[i]%mod;
reverse(w+,w+N);
fft(x,N);
reverse(w+,w+N);
for (int i=;i<N;i++) x[i]=x[i]*1ll*invN%mod;
for (int i=p-;i<N;i++) (x[i%(p-)]+=x[i])%=mod,x[i]=;
}
inline int solve(){
f[]=;
for (;n;n>>=) {
if (n&) muil(f,g);
muil(g,g);
}
return (f[ind[X]]+mod)%mod;
}
int main(){
prepare();
printf("%d\n",solve());
return ;
}

SDOI Day1的更多相关文章

  1. SDOI 2017 Day1

    日期:2017-04-10 题解: 第一题: 题目大意:求fi(gcd(i,j))的乘积  i,j属于[1,1e6],数据组数1000组. 类别:套路题. 第二题:BZOJ原题. 题解:LCT套线段树 ...

  2. 【BZOJ 4598】【SDOI 2016 Round2 Day1 T3】模式字符串

    2016-05-21因为BZOJ上“ 数据文件太过巨大,仅提供前三组数据测试.”所以我考场上写的60分的点分治交上去也A了. 我的这个点分治的时间复杂度是$O(Tnmlogn)$的,听题解时没听懂$O ...

  3. 【BZOJ 4515】【SDOI 2016 Round1 Day1 T3】游戏

    考场上写了lct,可惜当时对标记永久化的理解并不是十分深刻,导致调一个错误的程序调了4h+,最后这道题爆0了QwQ 现在写了树链剖分,用标记永久化的线段树维护轻重链,对于$s\rightarrow l ...

  4. SDOI 2016 Round1 Day1

    储能表 /* 引自zyz大佬的数学思想 */ #include<cstdio> #include<iostream> using namespace std; typedef ...

  5. SDOI 2019 R1游记

    $SDOI$ $2019$ $R1$游记 昨天才刚回来,今天就来写游记啦! Day -5: 做了一下去年省选的Day1,感觉很神仙. Day -4: 做了一下去年省选的Day2,感觉还是很神仙. Da ...

  6. SDOI 2019 R2 摸鱼记

    其实并没有什么动力来写这篇游记,毕竟呢,明明已经做好了被吊打的心理准备,可是当 Day 2 挂到没分时,当看到自己在高一里还排名二十时,还是有些,有些难言的滋味.学长们该走的真的都走了,就要只剩下 z ...

  7. SDOI 二轮垫底鸡

    SDOI 二轮垫底鸡 day0 准备爆零 没啥好准备考试的,12.00出发,试机敲抄个ntt,在宾馆不知道颓啥. day1 爆零爬山 T1noip的题目也放到省选上. 第一档线段树?肯定不写,直接上1 ...

  8. 【扯淡篇】CTSC/APIO/SDOI R2时在干什么?有没有空?可以来做分母吗?

    注意: 我比较弱, 并没有办法把外链bgm搞成https, 所以大家可以选择"加载不安全的脚本"或者把https改成http以获得更好的阅读体验! 据说, 退役了要写写回忆录. 但 ...

  9. NOIp2016 Day1&Day2 解题报告

    Day1 T1 toy 本题考查你会不会编程. //toy //by Cydiater //2016.11.19 #include <iostream> #include <cstd ...

随机推荐

  1. 查看Linux最近重启的时间

    最近实验室老是掉电,想查看服务器什么时候重启的,于是在网上找了一些资料.有两种方式可以查看服务器重启. (1) who -b (2) last reboot |head -1

  2. ServiceStack.Redis 使用链接池方法

    PooledRedisClientManager 1.RedisManage.cs public static class RedisManager { private static PooledRe ...

  3. 计时器chronometer补充

    项目中要实现关于安卓控件chronometer这部分的功能需求: 1.计时器的功能对用户答题时间进行时间统计,用户答完该题,进入下一题,计时器接续上一题的结束时间继续计时: 2.用户可以跳出答题界面, ...

  4. MySQL数据库面试

    1. MySql的存储引擎的不同 特点 Myisam BDB Memory InnoDB Archive 存储限制 没有 没有 有 64TB 没有 事务安全   支持   支持   锁机制 表锁 页锁 ...

  5. Git Flow——Git团队协作最佳实践

    规范的Git使用 Git是一个很好的版本管理工具,不过相比于传统的版本管理工具,学习成本比较高. 实际开发中,如果团队成员比较多,开发迭代频繁,对Git的应用比较混乱,会产生很多不必要的冲突或者代码丢 ...

  6. oralce

    1.对数据库SQL2005.ORACLE熟悉吗?   SQL2005是微软公司的数据库产品.是一个RDBMS数据库,一般应用在一些中型数据库的应用,不能跨平台.   ORACLE是ORACLE公司的数 ...

  7. delphi下实现控制其它窗体中的控件代码模板(delphi 7安装程序)

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  8. Windows server 2008 R2 64位系统安装ZendOptimizer-3.3.0a-Wind

    如果不安装ZEND的话,一些PHP网站程序使用ZEND加密后就无法使用,比如DISCUZ,SHOPEX,ECSHOP等,所以要想安装这些程序,ZEND是一定要安装的,要不会出现乱码等问题. 安装ZEN ...

  9. iOS 之 alcatraz (插件管理器)

    1. 安装 1.1. 打开命令行 curl -fsSL https://raw.githubusercontent.com/supermarin/Alcatraz/deploy/Scripts/ins ...

  10. c#使用DotNetZip封装类操作zip文件(创建/读取/更新)实例

    DotnetZip是一个开源类库,支持.NET的任何语言,可很方便的创建,读取,和更新zip文件.而且还可以使用在.NETCompact Framework中.  下载地址在这里:http://dot ...