(坐下来,喝了口水。。)
我:我要说的事,你们千万别害怕。
大佬A:这位先生,您放心,我们是大佬,我们不会怕。
我:我们明天早上,要打积分赛了!
大佬A:积分赛是哪个赛?
我:不是哪个赛,就是那个难得一批,让人自闭的那个。
大佬B–擦擦写写
刷“是这个吗?”———IOI(International Olympiad in Informatics )
我(吓得一哆嗦):没…没这么大,很小的,我们自己办的,就是一个小测试。
大佬B–擦擦写写
我(迫于大佬淫威):别写了,我跟你说,就是那个很小的,每周一次的积分赛!
大佬B:噗嗤…(秒变严肃)
我:你在笑什么?
大佬B:我想起高兴的事情。
我:什么高兴的事情?
大佬B:我上个星期出过一套题。
大佬A(捂脸笑…)
我:你又笑什么?
大佬A:我上个星期也出了一套题。
我:你们两个…出的是同一套题?我说上星期的题那么难,原来就是你们在搞我!?
大佬A、大佬B:对对(捂脸笑…)
我:(拍桌)我再重申一遍!我没在开玩笑!!
大佬A、大佬B:(捂脸笑…)
我:(疯狂拍桌)Why!!!
大佬A:(忍住笑)好,我们言归正传,你刚才说的那个积分赛,他难么?
我:它不是难不难的问题,它…它真的就是那种很特别的那种,它对你们来说很简单,但对我来说又刚好很难,就是那种能让你急得满地打滚,一题就能卡你几个小时的那种,它真的…
大佬B:噗嗤…
我:你欺人太甚!我忍你很久了!!
大佬B:我上个星期出过一套题。
我:你明明在笑我,你都没停过!!
大佬B:先生,我们受过严格的训练,无论多好笑呢,我们都不会笑,除非忍不住。。。
素数判定:
int isprime(int n)
{
if(n<=3) return n>1;
int k;
k=sqrt(n);
if(n%6!= 1 && n%6!=5)
return 0;
for(int i=5;i<=k;i+=6)
{
if(n%i==0 || n%(i+2)==0)
return 0;
}
return 1;
}
素数打表:
prim [1] = 1;
for (int i=2;i*i<TOP;i++)
If(! prim [i]) for (int j=i*i;j<TOP ;j+=i)
prim [j ]=1;
gcd(最大公因数):
int gcd(a, b) { //有一个函数—gcd()可直接用
return b ? gcd (b, a % b) : a;
}
快速幂:
ll pow_mod (ll a, ll n) {
ll res =
1;
while
(n) {
if(n&1) res = res * a % MOD ;
a = a * a % MOD;
n >>= 1;} return res ;}
矩阵快速幂:
定义结构体
node mull(node
a,node b) //对于有规律的数列,如斐波那契
{
在计算较高位数可以用
node res;
memset(res.ss,0,sizeof(res)); //想好怎么算再构造数组
for(int i=0;i<f;i++){
for(int j=0;j<f;j++){
for(int k=0;k<f;k++){
res.ss[i][j]=(res.ss[i][j]+a.ss[i][k]*b.ss[k][j]%mod)%mod;
}
}
}
return res;
}
node qpow(node
a,ll b)
{
node re;
memset(re.ss,0,sizeof(re.ss));
for(int i=0;i<f;i++)
re.ss[i][i]=1;
while(b)
{
if(b&1) re=mull(re,a);
b>>=1;
a=mull(a,a);
}
return re;
}
STL:也想不起来啥要写的(主要是学的太仓促)….
就记住每个函数的定义头文件吧
还有邻接表的封装:pari对vector : vector<pair<int, int> > v[maxn];
v[x].push_back(make_pair(y, z)); //建立邻接表
v[y].push_back(make_pair(x, z));```
struct 与vector :struct node
{
int x,y;
int step;//为当前步数
};
node[x].push_back({y,z});
node[y].push_back({x,z});
二分与贪心:
boolsolve(int v,intL,intR,int *a)//在区间下标为L~R的范围内查找v(必须是有序的)复杂度log2(n)
{
int mid;
mid=(R-L)/2+L;
while(L<=R){
if(a[mid]==v)
return true;
elseif(a[mid]<v)
L=mid;
else
R=mid;
}
return false;
}
lower_bound(a,a+n,k);(起始地址,末地址,查找元素)在区间(非降序)内返回第一个大于等于查找元素的地址,返回值是地址,不是下标需要减去首地址
upper_bound()返回第一个大于查找元素的地址
如果找不到,则返回末地址
二分搜索:通过不断缩小解可能存在的范围,从而求得问题最优解的方法,在程序设计竞赛中,经常可以见到二分搜索和其他算法结合的题目。
BFS与DFS:
DFS:一路走到黑,走迷宫,不撞南墙不回头,撞了墙就往回走一点(回溯)看看有没有其他的路,DFS中用到了回溯;
BFS:眼镜掉了,趴在地上摸眼镜,往周围一圈一圈的摸,慢慢摸到眼镜。
void
dfs(int deep)
{
int
x=deep/n,y=deep%n;
if(符合某种要求||已经不能在搜了)
{ 做一些操作;
return
;
}
if(符合某种条件且有地方可以继续搜索的)//这里可能会有多种条件,可能要循环什么的
{
a[x][y]='x';//可能要改变条件,这个是瞎写的
dfs(deep+1,sum+1);//搜索下一层
a[x][y]='.';//可能要改回条件,有些可能不用改比如搜地图上有多少块连续的东西
}
}
void dfs(int x,int y)
{
vst[x][y]=1; // 标记该节点被访问过
if(map[x][y]==G) // 出现目标态G
{
...... // 做相应处理
return;
}
for(int i=0;i<4;i++)
{
if(CheckEdge(x+dir[i][0],y+dir[i][1]))
// 按照规则生成下一个节点
dfs(x+dir[i][0],y+dir[i][1]);
}
return; // 没有下层搜索节点,回溯
}
/*
该DFS 框架以2D 坐标范围为例,来体现DFS 算法的实现思想。
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int map[maxn][maxn]; // 坐标范围
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向
bool CheckEdge(int x,int y) // 边界条件和约束条件的判断
{
if(!vst[x][y]
&& ...) // 满足条件
return 1;
else // 与约束条件冲突
return 0;
}
void dfs(int x,int y)
{
vst[x][y]=1; //
标记该节点被访问过
if(map[x][y]==G) // 出现目标态G
{
...... // 做相应处理
return;
}
for(int
i=0;i<4;i++)
{
if(CheckEdge(x+dir[i][0],y+dir[i][1])) // 按照规则生成下一个节点
dfs(x+dir[i][0],y+dir[i][1]);
}
return; // 没有下层搜索节点,回溯
}
int main()
{
......
return 0;
}
BFS:
int bfs(int x,int y)
{
queue<node>
q;
memset(vis,0,sizeof(vis));
vis[x][y]=1;
node
e,now,next;
e.x=x;
e.y=y;
e.step=0;
q.push(e);
while(!q.empty())
{
now=q.front();
q.pop();
int
d[8][2]={{-2,1},{-1,2},1,2,2,1,2,-1,1,-2,-1,-2,-2,-1};
for(int
i=0;i<8;i++)
{
next.x=now.x+d[i][0];
next.y=now.y+d[i][1];
if(next.x>=0&&next.y>=0&&next.x<n&&next.y<n&&!vis[next.x][next.y])
{
vis[next.x][next.y]=1;
next.step=now.step+1;
if(next.x==x2&&next.y==y2)
{
return
next.step;
}
q.push(next);
}
}
}
return 0;
}
01背包(取与不取,每个只能取一次):
for (int i=0;i<n;i++)
for (int j=0;j <=W;j++)
if(j<w[i])
dp[i +1][ j]= dp[i][j];
else
dp[i +1][ j]= max
(dp[i][j],dp[i][j-w[i]]+ v[i]);
printf ("%d\n",dp[n][W]);
int dp[ MAXN ];
for (int i=0;i<n;i++)
for (int j=W;j >=w[i];j
--)
dp[j]= max (dp[j],dp[j-w[i]]+ v[i]);
printf ("%d\n",dp[W]);
完全背包(每个可以取无数次):
for (int i=0;i<n;i++)
for (int j=0;j <=W;j++)
if(j<w[i])
dp[i +1][ j]= dp[i][j];
else
dp[i +1][ j]= max (dp[i][j],dp[i
+1][j-w[i]]+ v[i]);
printf ("%d\n",dp[n][W]);
int dp[ MAXN ];
for (int i=0;i<n;i++)
for (int j=w[i];j
<=W;j++)
dp[j]= max (dp[j],dp[j-w[i]]+ v[i]);
printf ("%d\n",dp[W]);
多重背包(每个可以取指定有限次):
for (int i=0;i<n;i ++){
int num =m[i];
for (int k=1; num >0;k
< <=1){
int mul =min (k,num );
for (int j=W;j >=w[i]*
mul;j - -){
dp[j]= max (dp[j],dp[j-w[i]* mul
]+v[i]* mul );
}
num -= mul;
}
}
printf ("%d\n",dp[W]);
(待续。。。)
3507

被折叠的 条评论
为什么被折叠?



