T1.破解D-H协议

传送门

这个题就是BSGS的板子题……

然后这里补充一点嘛,就是第二重循环的枚举范围。我们是在枚举\(a^{tm-y}\),把tm换成i,这个的最大值就是\(i - (m - 1) < c\),即\(i < c + m - 1\)

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = 200005;
const int mod = 999979; int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans *= 10,ans += ch - '0',ch = getchar();
return ans * op;
} int g,P,n,A,B; struct Hash
{
int sta[M],top,head[M<<3],ecnt,num[M],val[M],nxt[M];
void init(){ecnt = 0;while(top) head[sta[top--]] = 0;}
void insert(int x,int y)
{
int h = x % mod;
for(int i = head[h];i;i = nxt[i]) if(num[i] == x) {val[i] = y;return;}
if(!head[h]) sta[++top] = h;
nxt[++ecnt] = head[h],head[h] = ecnt;
num[ecnt] = x,val[ecnt] = y;
}
int query(int x)
{
int h = x % mod;
for(int i = head[h];i;i = nxt[i]) if(num[i] == x) return val[i];
return -1;
}
}H; int mul(int a,int b,int t){return 1ll * a * b % t;}
int qpow(int a,int b,int t)
{
int p = 1;
while(b)
{
if(b & 1) p = mul(p,a,t);
a = mul(a,a,t),b >>= 1;
}
return p;
}
int gcd(int a,int b){return b ? gcd(b,a%b) : a;}
int exgcd(int a,int b,int &x,int &y)
{
if(!b){x = 1,y = 0;return a;}
int d = exgcd(b,a%b,y,x);
y -= a / b * x;
return d;
} int inv(int a,int b)
{
int x,y;
exgcd(a,b,x,y);
return (x % b + b) % b;
} int BSGS(int a,int b,int c)
{
int cnt = 0,G,d = 1;
while((G = gcd(a,c)) != 1)
{
if(b % G) return -1;
cnt++,b /= G,c /= G,d = mul(d,a/G,c);
}
b = mul(b,inv(d,c),c);
H.init();
int s = sqrt(c),p = 1;
rep(i,0,s-1)
{
if(p == b) return i + cnt;
H.insert(mul(p,b,c),i),p = mul(p,a,c);
}
int q = p,t;
for(int i = s;i <= c + s - 2;i += s)
{
t = H.query(q);
if(t != -1) return i - t + cnt;
q = mul(q,p,c);
}
return -1;
} int main()
{
g = read(),P = read(),n = read();
rep(i,1,n)
{
A = read(),B = read();
int a = BSGS(g,A,P);
int b = BSGS(g,B,P);
printf("%d\n",qpow(g,mul(a,b,P-1),P));
}
return 0;
}

T2.社交网络

传送门

这个题是有向图有根树生成树计数,根必须为1.

其实和无向图的生成树计数基本是一样的……就是这次的基尔霍夫矩阵按照有向图来建造。

然后因为根是1,所以我们把矩阵的第一行和第一列删掉,剩下的用高斯消元就可以了。

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = 255;
const int mod = 1e4+7; int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans *= 10,ans += ch - '0',ch = getchar();
return ans * op;
} int n,m,x,y,f[M][M];
int inc(int a,int b){return (a + b) % mod;}
int mul(int a,int b){return 1ll * a * b % mod;}
int qpow(int a,int b)
{
int p = 1;
while(b)
{
if(b & 1) p = mul(p,a);
a = mul(a,a),b >>= 1;
}
return p;
} int gauss()
{
int ans = 1;
rep(i,2,n)
{
rep(j,i+1,n) if(f[j][i]) {swap(f[j],f[i]),ans = mod - ans;break;}
if(!f[i][i]) return 0;
ans = mul(ans,f[i][i]);
int inv = qpow(f[i][i],mod-2);
rep(j,i+1,n)
{
int cur = mul(f[j][i],inv);
rep(k,i,n) f[j][k] = inc(f[j][k],mod - mul(f[i][k],cur));
}
}
return ans;
} int main()
{
n = read(),m = read();
rep(i,1,m) x = read(),y = read(),f[x][x]++,f[x][y]--;
printf("%d\n",gauss());
return 0;
}

T3.交错序列

传送门

个人认为是最难的一道了……

\(x^ay^b\)难以处理,于是我们转化为\((n-y)^ay^b\),那么展开以后就是\(\sum_{i=0}^a(-1)^{a-i}n^iC_a^iy^{a+b-i}\)

于是我们只要求出\(y^i\)的和就可以了。我们可以考虑DP。

用\(dp[i][j][0/1]\)表示当前选取到长度为i,当前位为0/1,当前序列中1的个数的j次方之和。

然后对于0/1变0的情况是没有什么变化的,就是\(dp[i][j][0] += dp[i-1][j][0/1]\)

如果这一位是1的话,根据二项式定理就可以得到\(dp[i][j][1] += \sum_{k=0}^jC_j^kdp[i-1][k][0]\)

于是这个可以用矩阵乘法优化。然后我写完之后还被卡常了……把矩乘内部开成ll,最内一层循环不取模就过了……

最后就按照上面的式子计算答案。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = 200005;
const int N = 185;
const int mod = 999979; int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans *= 10,ans += ch - '0',ch = getchar();
return ans * op;
} int n,a,b,m,siz,C[N][N],ans;
int inc(int a,int b){return (a + b) % m;}
int mul(int a,int b){return 1ll * a * b % m;} struct matrix
{
ll f[N][N];
matrix(){memset(f,0,sizeof(f));}
void init(){rep(i,0,siz-1) f[i][i] = 1;}
friend matrix operator * (const matrix &a,const matrix &b)
{
matrix c;
rep(i,0,siz-1)
rep(j,0,siz-1)
{
rep(k,0,siz-1) c.f[i][j] += a.f[i][k] * b.f[k][j];
c.f[i][j] %= m;
}
return c;
}
friend matrix operator ^ (matrix a,int b)
{
matrix p;
p.init();
while(b)
{
if(b & 1) p = p * a;
a = a * a,b >>= 1;
}
return p;
}
}G; int main()
{
n = read(),a = read(),b = read(),m = read(),siz = (a+b+1) << 1;
C[0][0] = 1;
rep(i,1,a+b)
{
C[i][0] = 1;
rep(j,1,i) C[i][j] = inc(C[i-1][j-1],C[i-1][j]);
}
rep(i,0,a+b)
{
G.f[i][i] = G.f[i][i+a+b+1] = 1;
rep(j,0,i) G.f[i+a+b+1][j] = C[i][j];
}
G = G ^ n;
int cur = 1;
rep(i,0,a)
{
int now = ((a - i) & 1) ? -1 : 1;
ans = inc(ans,mul(mul(cur,C[a][i]),mul(now,inc(G.f[a+b-i][0],G.f[siz-1-i][0]))));
cur = mul(cur,n);
}
printf("%d\n",(ans % m + m) % m);
return 0;
}

T4.解锁屏幕

传送门

这题挺好玩啊。

但是可以显而易见的看出是状压DP。然后转移也很好想……

\(dp[i][j]\)表示选取集合i,末尾为j的方案数。转移的时候枚举点,按照题中条件判断即可。然后注意在两点连线上的点需要预处理。

然后注意答案要连四个及以上的点,模数是1e8+7。其实很奇怪这玩意复杂度最坏是\(2^nn^2\)的,但是就是过了……

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = 1000005;
const int mod = 1e8+7; int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans *= 10,ans += ch - '0',ch = getchar();
return ans * op;
} struct dot
{
double x,y;
}a[25]; int n,G[25][25],dp[1<<20][21],ans;
int inc(int a,int b){return (a+b) % mod;}
double slope(const int &f,const int &g) {return (a[g].y - a[f].y) / (a[g].x - a[f].x);}
bool in(int i,int j,int k)
{
if((a[k].y >= a[i].y && a[k].y <= a[j].y) || (a[k].y >= a[j].y && a[k].y <= a[i].y))
{
if((a[k].x >= a[i].x && a[k].x <= a[j].x) || (a[k].x >= a[j].x && a[k].x <= a[i].x)) return 1;
}
return 0;
} int count(int x)
{
int cur = 0;
while(x) cur += x & 1,x >>= 1;
return cur;
} int main()
{
n = read();
rep(i,0,n-1) scanf("%lf%lf",&a[i].x,&a[i].y),dp[1<<i][i] = 1;
rep(i,0,n-1)
rep(j,0,n-1)
rep(k,0,n-1)
{
if(k == i || k == j) continue;
if(in(i,j,k))
{
//printf("%d %d %d\n",i,j,k);
if(a[k].x == a[i].x && a[k].x == a[j].x) G[i][j] |= (1<<k);
else if(slope(i,j) == slope(k,j)) G[i][j] |= (1<<k);
}
}
//rep(i,0,n-1)
//{rep(j,0,n-1) printf("$%d ",G[i][j]);enter;}
rep(i,1,(1<<n)-1)
{
rep(j,0,n-1)
{
if(!(i & (1 << j))) continue;
rep(k,0,n-1)
{
if(i & (1<<k)) continue;
if((i & G[j][k]) != G[j][k]) continue;
dp[i | (1<<k)][k] = inc(dp[i][j],dp[i | (1<<k)][k]);
}
}
}
//rep(i,1,(1<<n)-1)
//{rep(j,0,n-1) printf("#%d ",dp[i][j]);enter;}
rep(i,1,(1<<n)-1)
{
if(count(i) < 4) continue;
rep(j,0,n-1) if(i & (1 << j)) ans = inc(ans,dp[i][j]);
}
printf("%d\n",ans);
return 0;
}

T5.九连环

传送门

听说这题在数学书上有……?还是必修五?

emm可能是A版……? 反正我的B版上没有TAT。

然后通过爆搜通过百度知道,答案就是\(\lfloor\frac{2^n+1}{3}\rfloor\)

然后就写一下FFT就能过…… 不过我太懒了 我用了python。 代码没有。

T6.异或序列

这个以前写过。看这里

CQOI2018做题记录的更多相关文章

  1. UOJ 做题记录

    UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...

  2. project euler做题记录

    ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{a ...

  3. Sam做题记录

    Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...

  4. 退役IV次后做题记录

    退役IV次后做题记录 我啥都不会了.... AGC023 D 如果所有的楼房都在\(S\)同一边可以直接得出答案. 否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车 ...

  5. 退役III次后做题记录(扯淡)

    退役III次后做题记录(扯淡) CF607E Cross Sum 计算几何屎题 直接二分一下,算出每条线的位置然后算 注意相对位置这个不能先搞出坐标,直接算角度就行了,不然会卡精度/px flag:计 ...

  6. 退役II次后做题记录

    退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...

  7. BJOI做题记录

    BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...

  8. FJOI2017前做题记录

    FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...

  9. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

随机推荐

  1. MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现

    原文链接:http://hi.baidu.com/wangzhiqing999/item/7ca215d8ec9823ee785daa2b MySQL 下 ROW_NUMBER / DENSE_RAN ...

  2. node.js实现国标GB28181流媒体点播(即实时预览)服务解决方案

    背景 28181协议全称为GB/T28181<安全防范视频监控联网系统信息传输.交换.控制技术要求>,是由公安部科技信息化局提出,由全国安全防范报警系统标准化技术委员会(SAC/TC100 ...

  3. oracle img 导入dmp文件

    1.新建表空间 因为我们导出的数据表的表空间不一定是USERS, 假如说是:FQDB 新建表空间SQL语句 create tablespace FQDB datafile 'c:\FQDB.dbf' ...

  4. python字典中包含列表时:查找字典中某个元素及赋值

    直接上代码: 运行效果:

  5. 【Robot Framework】---- Robot Framework简介、特点、RIDE

    Robot Framework简介.特点.RIDE 一.简介.特点. Robot Framework是一款python编写的功能自动化测试框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型 ...

  6. java上传文件,下载文件

    1.上传文件 1 protected int doTask(BaseForm form) throws AppException, FatalException, NoExistsException, ...

  7. ubuntu14.04允许root远程链接、修改主机名

    1.设置root密码 sudo passwd root 2.修改主机名 第一步:ubuntu主机名位于/etc/hostname里,将其修改为自己需要的名称. 第二步:修改/etc/hosts文件,将 ...

  8. sql获取数组指定元素

    需求:获取字符数组1,2,3的第2个元素 方法:通过自定义函数来实现 /* 获取字符串数组某个元素 */ from sysobjects where id = object_id('Get_StrAr ...

  9. Mysql的空值与NULL的区别

    Mysql数据库是一个基于结构化数据的开源数据库.SQL语句是MySQL数据库中核心语言.不过在MySQL数据库中执行SQL语句,需要小心两个陷阱. 陷阱一:空值不一定为空 空值是一个比较特殊的字段. ...

  10. 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈

    题目 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小的元素的操作 要求 1. pop.push.getMin操作时间复杂度都是O(1) 2. 设计的栈类型可以使用现成的栈结构 java代码 ...