【dfs/bfs+set+快速幂】swjtuOJ 2094

【dfs/bfs+set+快速幂】swjtuOJ 2094

【注:交大的看到这篇文章要学会自己写,不要为了比赛而比赛!~】

题目大意

问题一:主人公去度假,问经过a^b天后是星期几(简单题)

问题二:一个天平,n个重物,每个物体的重量wi已知,问能称出的所有重量有多少种?

问题二要注意到天平两侧都可以放重物,每一个重物的权值都可以赋值为w,0,-w,相当于三分,我们知道二分可以用二进制位运算进行枚举,例如:枚举所有子集

    int j,k,top=0;
    int t = 1 << n;
    for(int i = 0;i < t; ++ i){//位运算枚举子集,O(N*2^N)
        j = i;
        k = 0;
        while(j){
          if(j&1) printf("%d ",w[k]);
          j >>= 1;
          ++ k;
        }
        printf("\n");
    }

这道三分的问题直接搜索了,母函数解决不了(w太大存不下), 搜索dfs和bfs都可以,很裸的搜索了,去重用set神器!O(∩_∩)O~

【注意】求的和是负值也是有效的,abs后扔进set里面~~~

说一下思路

  • 问题一:整数快速幂,题目1<=a,b<=10有误,a,b范围很大的
  • 问题二:和之前说的思路一致,直接搜索,我写了两版,供读者参考,求出来的和扔进set容器里面自动去重了,最后输出set的大小和最后一个数值(自动排序后最后一个数肯定为所有物体重量w之和)

?set和map的比较:map最大优点是映射,对于存储数字序列,也有自动去重、自动排序的功能,还可以映射出该数字出现的次数(在值域之中it->second);set是不可重复的多元集合,最大特点在于去重,而且默认排序。总之,去重神器set Orz~


参考代码一:dfs

/*====================================*|* set去重+三种状态枚举子集:dfs + bfs*|
|*  两种状态可以用二进制位运算解决    *|
\*====================================*/
/*Author:Hacker_vision*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<set>
#define clr(k,v) memset(k,v,sizeof(k))
#define ll long long
#define eps 1e-8
using namespace  std;

const int _max = 4e6 + 10;
const int mod = 7;
int a,b,n,w[20];
struct node{
  int num;
  ll sum;
};
set<ll>s;

void dfs(int deep,ll tot){//深度优先搜索
 if(deep==n){
    if(tot) s.insert(abs(tot));
    return;
 }
 dfs(deep+1,tot);
 dfs(deep+1,tot-w[deep]);
 dfs(deep+1,tot+w[deep]);
}

ll quick_mod(ll a,ll b){//矩阵快速幂
  ll ans = 1;
  while(b){
    if(b&1) ans = (ans*a)% mod;
    b >>= 1;
    a = (a * a) % mod;
  }
  return ans;
}

int main(){
  #ifndef ONLINE_JUDGE
  freopen("input.txt","r",stdin);
  #endif // ONLINE_JUDGE
  while(scanf("%d%d",&a,&b)==2){
    ll d = quick_mod((ll)a,(ll)b);
    if(d%7==0||d%7==6) printf("800 ");
    else printf("1000 ");
    scanf("%d",&n);
    for(int i = 0; i < n; ++ i){
        scanf("%d",w+i);
    }
    s.clear();
    dfs(0,0);
    set<ll>::reverse_iterator it = s.rbegin();//反向迭代器
    printf("%d %lld\n",s.size(),*it);
  }
  return 0;
}

参考代码二:bfs

/*====================================*|* set去重+三种状态枚举子集:dfs + bfs*|
|*  两种状态可以用二进制位运算解决    *|
\*====================================*/
/*Author:Hacker_vision*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<set>
#define clr(k,v) memset(k,v,sizeof(k))
#define ll long long
#define eps 1e-8
using namespace  std;

const int _max = 4e6 + 10;
const int mod = 7;
int a,b,n,w[20];
struct node{
  int num;
  ll sum;
};
set<ll>s;
queue<node>Q;

void bfs(){ //广度优先搜索
  node q;
  q.num = 0;
  q.sum = 0;
  Q.push(q);
  while(!Q.empty()){
    q = Q.front();
    Q.pop();
    if(q.num==n){
        if(q.sum>0) s.insert(q.sum);
        continue; //return;最短路是return
    }
    node p;p.num = q.num + 1;
    for(int i = 0; i < 3; ++ i){
        if(i == 0) {
            p.sum = q.sum ;
        }
        else if(i == 1){
            p.sum = q.sum + w[q.num];
        }
        else p.sum = q.sum - w[q.num];
        Q.push(p);
    }
  }
}

ll quick_mod(ll a,ll b){//矩阵快速幂
  ll ans = 1;
  while(b){
    if(b&1) ans = (ans*a)% mod;
    b >>= 1;
    a = (a * a) % mod;
  }
  return ans;
}

int main(){
  #ifndef ONLINE_JUDGE
  freopen("input.txt","r",stdin);
  #endif // ONLINE_JUDGE
  while(scanf("%d%d",&a,&b)==2){
    ll d = quick_mod((ll)a,(ll)b);
    if(d%7==0||d%7==6) printf("800 ");
    else printf("1000 ");
    scanf("%d",&n);
    for(int i = 0; i < n; ++ i){
        scanf("%d",w+i);
    }
    s.clear();
    while(!Q.empty()) Q.pop();
    bfs();
    set<ll>::reverse_iterator it = s.rbegin();//反向迭代器
    printf("%d %lld\n",s.size(),*it);
  }
  return 0;
}
  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-28 22:19:15

【dfs/bfs+set+快速幂】swjtuOJ 2094的相关文章

第三次周赛题解【并查集 KMP DFS BFS 快速幂】

问题 A: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 63  解决: 28 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数.循环节以及循环节长度 输入 输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100 输出 分别输出这个小数的循环节的长度.循环节以及循环次数,中间以

WustOJ 1575 Gingers and Mints(快速幂 + dfs )

1575: Gingers and Mints Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: 24  Accepted: 13[Submit][Status][Web Board] Description fcbruce owns a farmland, the farmland has n * m grids. Some of the grids are stones, rich soil i

K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)

题目链接:http://codeforces.com/gym/101466/problem/K 题目: 题意: 给你一棵有n个节点的树,根节点始终为0,有两种操作: 1.RAND:查询以u为根节点的子树上的所有节点的权值的乘积x,及x的因数个数. 2.SEED:将节点u的权值乘以x. 思路: 比赛时少看了因数不大于13这句话,然后本题难度增加数倍,肝了两个小时都没肝出来,对不起队友啊,今天的组队训练赛实力背锅…… 这题一眼线段树,由于是对一棵子树进行处理,因此我们采用常规套路,借助dfs序将子树

瓷砖铺放 (状压DP+矩阵快速幂)

未加矩阵快速幂 50分 1 const dx:array[1..8,1..3] of longint= 2 ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1)); 3 dy:array[1..8,1..3] of longint= 4 ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0)); 5 mo=65521; 6 va

矩阵快速幂的一份小结

矩阵真是个好东西!虽然矩乘的复杂度有点难看... ... 这几天也做了不少矩阵题目,还是有几道好题目的.不过我打算从入门开始. 矩阵乘法:A[i][k]*B[k][j]=C[i][j];(A的第i行的每项依次乘以B的第j列的每项的和) 很显然这是一个n^3的算法,还是比较难看的. 代码就差不多是这样了. struct Matrix{int T[51][51];}; Matrix Mul(Matrix a,Matrix b,int I,int K,int J) { Matrix S=S0; for

【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. 在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论起了二叉搜索树.什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树.设key[p]表示结点p上的数值.对于其中的每个结点p,若其存在左孩子lch,则key

快速幂-(复习)

快速幂要用二分指数的办法来计算, 一般只用把结果取余就可以了 例题 NOIP2013提高组day2第一题 转圈游戏 读题可以知道本题就是求(10^k*m+x)%n 就求10^k%n 可以用记忆化搜索,记得不要dfs两次一样的,设个long long 保存 但也可用直接 用二进制来分解K 一下是最后一种代码 #include <iostream>#include<cstdio>using namespace std;long long n,m,x,k,a=10,ys=1;int ma

hdu 2604 Queuing dp找规律 然后矩阵快速幂。坑!!

http://acm.hdu.edu.cn/showproblem.php?pid=2604 这题居然O(9 * L)的dp过不了,TLE,  更重要的是找出规律后,O(n)递推也过不了,TLE,一定要矩阵快速幂.然后立马GG. 用2代表m,1代表f.设dp[i][j][k]表示,在第i位,上一位站了的人是j,这一位站的人是k,的合法情况. 递推过去就是,如果j是1,k是2,那么这一位就只能放一个2,这个时猴dp[i][k][2] += dp[i - 1][j][k]; 其他情况分类下就好,然后

HUST 1569(Burnside定理+容斥+数位dp+矩阵快速幂)

传送门:Gift 题意:由n(n<=1e9)个珍珠构成的项链,珍珠包含幸运数字(有且仅由4或7组成),取区间[L,R]内的数字,相邻的数字不能相同,且旋转得到的相同的数列为一种,为最终能构成多少种项链. 分析:这是我做过的最为综合的一道题目(太渣了),首先数位dp筛选出区间[L,R]内的幸运数字总数,dp[pos]表示非限制条件下还有pos位含有的幸运数字个数,然后记忆化搜索一下,随便乱搞的(直接dfs不知会不会超时,本人做法900+ms险过,应该直接dfs会超时),再不考虑旋转相同的情况,可以