铁板铮铮♂+习题集
Posted brokenstring
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了铁板铮铮♂+习题集相关的知识,希望对你有一定的参考价值。
数论
-
快速幂
当b为偶数:ab=ab/2 * ab/2
当b为奇数:ab=ab/2 * ab/2 * a
核心代码:
int quickpow(int a,int b) { int ret=1; for(;b;b>>=1)//如果b不等于0 b除2 { if(b&1)//b是奇数 ret=ret*a%n; a=a*a%n; } return ret; }
题目号 | 题目名 | 注释 |
洛谷P1965 | 【NOIP2013TG】转圈游戏 | 简单推导公式 |
洛谷P3197 |
【HNOI2008】越狱 |
与组合数学结合 |
-
线性筛
#include<iostream> using namespace std; #define maxn 10000001 int prime[maxn],v[maxn],f[maxn];//prime为素数表 //v为每个数的最小质因子 //f数组判断是否是素数 int n,m,k; void primes(int n) { k=0; for(int i=2;i<=n;i++)//从2开始 { if(v[i]==0) { v[i]=i;//i是质数,则i的最小质因子为本身 prime[++k]=i; f[i]=1; } for(int j=1;j<=k;j++) { if(prime[j]>v[i]||prime[j]*i>n) break; //如果i有比prime[j]更小的质因子 //或者超出n的范围 v[i*prime[j]]=prime[j];//prime[j]是合数i*prime[j]的最小质因子 } } } int main() { cin>>n>>m; primes(n); for(int i=1;i<=m;i++) { int x; cin>>x; if(f[x]==1) cout<<"Yes"<<endl; else cout<<"No"<<endl; } }
题目号 | 题目名 | 注释 |
洛谷P3383 | 线性筛素数 | 模板题 |
-
质因数分解
void divide(int x) { m=0; for(int i=2;i*i<=n;i++)//一个数至多只有一个大于根号n的质因子 //所以后面特判 前面只要到根号n { if(n%i==0)//i是质数 { p[++m]=i; c[m]=0; } while(n%i==0) { n=n/i;//除掉所有的i c[m]++; //i的指数加1 } } if(n>1)//特判大于根号n的那个 { p[++m]=n; c[m]=1; } }
题目号 | 题目名 | 注释 |
洛谷P1075 | 【NOIP2012PJ】质因数分解 | 模板题 |
洛谷P2926 | 【USACO08DEC】Patting Heads | |
Codeforces 776B | Sherlock and his girlfriend | |
洛谷P1463 | 【HAOI2007】反素数 |
-
gcd与lcm
辗转相除法求gcd
int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); }
求lcm:
a*b=gcd(a,b)*lcm(a,b)
题目号 | 题目名 | 注释 |
洛谷P1072 | 【NOIP2009TG】Hankson的趣味题 | |
POJ3421 | X-factor Chains |
-
扩展欧几里得exgcd
void exgcd(int a,int b,int &d,int &x,int &y) { int t; if(b==0)//当b=0时 gcd(a,b)=a //因为1*a+0*0=a 所以ax+by=gcd(a,b)有一组解为 //x=1 y=0 { d=a; x=1; y=0; } else { exgcd(b,a%b,d,x,y); t=x;//推导得公式 x=y; y=t-(a/b)*y; } }
题目号 | 题目名 | 注释 |
洛谷P1516 | 青蛙的约会 | |
洛谷P1082 | 【NOIP2012TG】同余方程 |
-
乘法逆元
-
中国剩余定理
动态规划
-
区间DP
枚举所有在i与j之间的k
把一段区间分成两段为两个状态
如果是环形可以考虑断环成链 开数组2n
初始化 f[i][i]=1或者权值
答案要枚举所有的左端点到后n位
核心代码:
f1[i][j]=max(f1[i][j],f1[i][k]+f1[k+1][j]+sum[j]-sum[i-1]); f2[i][j]=min(f2[i][j],f2[i][k]+f2[k+1][j]+sum[j]-sum[i-1]);
题目号 | 题目名 | 注释 |
洛谷P1880 | 【NOI1995】石子合并 | 断链成环 |
洛谷P1063 | 能量项链 | 中等难度 |
洛谷P2426 | 删数 | 从两边删除区间 |
洛谷P3146 | 【USACO160PEN】248 | 类似2048游戏 |
洛谷P1005 | 【NOIP2007TG】矩阵取数游戏 | 高精+翻倍 |
洛谷P3205 | 【HNOI2010】合唱队 | 用两个数组 |
图论
-
并查集:
#include<iostream> using namespace std; int father[5001]; int n,m,p; int find(int x) { if(father[x]!=x)//路径压缩优化 father[x]=find(father[x]);//把路上的所有点祖先全部改掉 return father[x]; } void unionn(int x,int y) { father[y]=x;//y的祖先为x的祖先 //相当于合并祖先 } int main() { cin>>n>>m>>p; for(int i=1;i<=n;i++) { father[i]=i;//所有数据初始祖先为自己 //独立的一个数为一个集合 } for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; int r1,r2; r1=find(x); r2=find(y);//寻找两个数的祖先 if(r1!=r2)//如果不是同一个祖先 { unionn(r1,r2);//合并 } } for(int i=1;i<=p;i++) { int x,y; cin>>x>>y; if(find(x)==find(y))//如果是同一个祖先 { cout<<"Yes"<<endl;//是 } else cout<<"No"<<endl;//否 } }
题目号 | 题目名 | 注释 |
洛谷P3367 | 【模板】并查集 | 如题 |
洛谷P2024 |
【NOI2001】食物链 |
搞好三者关系 |
洛谷P1525 |
关押罪犯 |
排序+并查集 |
洛谷P1111 |
修复公路 |
eazy |
洛谷P1197 |
【JSOI2008】星球大战 |
逆向思维 |
-
最小生成树:
Kruskal
#include<iostream> #include<algorithm> using namespace std; struct edge { int l,r,w;//左端点 右端点 权值 }e[200001]; int father[5001]; int n,m,k=0,tot; bool cmp(const edge &a,const edge &b)//用权值排序 { if (a.w<b.w) return 1; else return 0; } int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void unionn(int x,int y) { int fa=find(x); int fb=find(y); if(fa!=fb) father[fa]=fb; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) father[i]=i; for(int i=1;i<=m;i++) { cin>>e[i].l>>e[i].r>>e[i].w; } sort(e+1,e+1+m,cmp); for(int i=1;i<=m;i++) { if(find(e[i].l)!=find(e[i].r)) { unionn(e[i].l,e[i].r); tot+=e[i].w; k++; } if(k==n-1) break;//到n-1条时退出 } cout<<tot; }
题目号 | 题目名 | 注释 |
洛谷P3366 | 【模板】最小生成树 | 如题 |
洛谷P1195 | 口袋的天空 | 处理边的关系 |
洛谷P2330 | 【SCOI2005】繁忙的都市 | 记下最大值 |
以上是关于铁板铮铮♂+习题集的主要内容,如果未能解决你的问题,请参考以下文章