2017百度之星初赛

本文总结了2017年百度之星初赛的算法问题,包括小C的倍数问题、数据分割、路径交、今夕何夕和度度熊的01世界。针对每个问题,提供了问题描述、解题思路和AC代码,帮助读者理解并解决这些算法挑战。
摘要由CSDN通过智能技术生成

A汇总(无1004 迷宫出逃)
结合自己理解和网上题解汇总了一下2017百度之星初赛的题解,暂无0ak的1004题

小C的倍数问题

Accepts: 1990 Submissions: 4931
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description
根据小学数学的知识,我们知道一个正整数x是3的倍数的条件是x每一位加起来的和是3的倍数。反之,如果一个数每一位加起来是3的倍数,则这个数肯定是3的倍数。

现在给定进制P,求有多少个B满足P进制下,一个正整数是B的倍数的充分必要条件是每一位加起来的和是B的倍数。

Input
第一行一个正整数T表示数据组数(1<=T<=20)。

接下来T行,每行一个正整数P(2 < P < 1e9),表示一组询问。

Output
对于每组数据输出一行,每一行一个数表示答案。

Sample Input
1
10
Sample Output
3

假设一个数为 : p 进制下的 a1a2a3 % B == 0,者以下俩个等式一定成立:
1)a1 * p ^ 2 + a2 * p ^ 1 + a3 * p ^ 1 = sum % B == 0,
2)a1 + a2 + a3 = ans % B == 0

以上两个式子同时成立的条件是 : p % B == 1
所以满足条件的 B 的个数为 p - 1 的因子数

AC代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 1e5 + 10;
typedef long long LL;
void solve(LL o){
    int ans = 0;
    for(LL i = 1; i * i <= o; i++){
        if(o % i == 0){
                ans++;
            if(i * i != o) ans++;
        }
    }
    printf("%d\n",ans);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        LL n;
        scanf("%lld",&n);
        solve(n - 1);
    }
    return 0;
}

数据分割

小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统。

这个程序接受一些形如x_i = x_jx​i​​=x​j​​ 或 x_i \neq x_jx​i​​≠x​j​​ 的相等/不等约束条件作为输入,判定是否可以通过给每个 w 赋适当的值,来满足这些条件。

输入包含多组数据。 然而粗心的小w不幸地把每组数据之间的分隔符删掉了。 他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的。

请帮助他恢复这些分隔符。

Input
第11行:一个数字LL,表示后面输入的总行数。

之后LL行,每行包含三个整数,i,j,ei,j,e,描述一个相等/不等的约束条件,若e=1e=1,则该约束条件为x_i = x_jx​i​​=x​j​​ ,若e=0e=0,则该约束条件为 x_i \neq x_jx​i​​≠x​j​​ 。

i,j,L \leq 100000i,j,L≤100000

x_i , x_j \leq Lx​i​​,x​j​​≤L

Output
输出共T+1T+1行。

第一行一个整数TT,表示数据组数。

接下来TT行的第ii行,一个整数,表示第i组数据中的约束条件个数。

Sample Input
6
2 2 1
2 2 1
1 1 1
3 1 1
1 3 1
1 3 0
Sample Output
1
6
———————————————————————————————————————
因为相等具有传递性所以我们可以用并查集维护一波
但是不能不具有传递性所以我们可以用平衡树维护一波
当然这里我用的是set
这样之后呢 等于我们就可以把他们扔在一个并查集里面
不等于的就把不等于他的扔进他的平衡树里面
每次询问
如果是一对相等的数
我们就找一波他们是否在同一个并查集里 是就直接继续下一波
不是就找他们是否存在对方的并查集里面 当然这里我们强行把size小的合并进大的里面保证复杂度
如果是不想等就判短他们是否同属一个并查集
是就清空一波 记录答案
不然就把他们加入对方的平衡树里面

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){
  if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int T,f[200007];
int find(int x){
  return f[x]==x?x:f[x]=find(f[x]);}
set<int>tr[200007];
int vis[200007],cnt=1;
int ans[200007],ap;
int stk[200007],stp;
int a,b,h;
void clear(){
    while(stp){
        int x=stk[--stp];
        tr[x].clear();
        f[x]=x;
    }
    ++cnt;
}
int main()
{
    T=read();
    for(int i=0;i<=200000;i++) f[i]=i;
    for(int i=1;i<=T;i++){
        a=read(); b=read(); h=read();
        if(vis[a]!=cnt) stk[stp++]=a,vis[a]=cnt;
        if(vis[b]!=cnt) stk[stp++]=b,vis[b]=cnt;
        int p=find(a),q=find(b);
        if(tr[p].size()<tr[q].size()) swap(p,q);
        if(h==1){
            if(p==q) continue;
            if(tr[p].find(q)!=tr[p].end()){
                clear();
                ans[++ap]=i;
                continue;
            }
            f[q]=p;
            for(set<int>::iterator it=tr[q].begin();it!=tr[q].end();it++){
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值