Thursday, November 22, 2018

Android 启动显示对话框


可以使用Recevier启动透明Activity来实现

Recevier 实现

网络上很多
具体Receiver的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.myapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
            Intent i = new Intent(context, DialogActivity.class);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        }
    }
}

透明 Activity 实现

styles.xml 中加入, 透明 sytle

1
2
3
4
5
6
7
8
9
<style name="Theme.AppCompat.Translucent">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>
然后在AndroidManifest.xml中你想要启动的那个activityTheme设置为Theme.AppCompat.Translucent

1
2
3
<activity android:name=".DialogActivity"
          android:theme="@style/Theme.AppCompat.Translucent">
</activity>

对话框实现

这个网上也很多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.example.myapplication;

import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class DialogActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog);

        AlertDialog dialog = new AlertDialog
                .Builder(this)
                .setTitle("title")
                .setMessage('content')
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                })
                .create();
        dialog.show();
    }
}

Wednesday, November 21, 2018

算法题-推荐潜在好友

昨天写的一道算法题
图算法:推荐潜在好友 by Hongzhi Shi
时间限制: 2000 ms 内存限制: 6000 KB
但是跟图算法没半毛钱关系
关键是过内存上的限制

问题描述

社交网络可以用一个图来描述。假定有N个使用者,每个使用者可以用一个节点表示,如果使用者m和使用者n已经是线上朋友,表示两个节点已经连接,即图中包含连接m和n的边。在这个练习中,我们将为使用者推荐可能的朋友。
给定表示一个社交网络的图,包含N个节点和M条边。如果节点m和n不直接相连,但与K个以上(包括K个)的相同节点连接,我们可以认为他们可能认识,请给出指定用户的潜在好友(暂时还未直接连接的节点)。对于给定用户,请将其所有潜在好友按照他们共同好友数量由多到少排列输出,对于共同好友数量相同的情况,请按照序号从小到大排列输出。

输入格式

输入的第一行是三个整数N,K,U。其中N表示社交网络中用户的个数,即网络节点的个数。K表示共同好友数不少于K的两个用户才互相算作潜在好友。U表示需要输出标号为U的用户的潜在好友,对应矩阵行/列标号为U的节点,U从0开始计。
输入的第二行到第N+1行是用户之间的图的邻接矩阵:0代表不是好友,1代表是好友。

输出格式

输入的第一行是三个整数N,K,U。其中N表示社交网络中用户的个数,即网络节点的个数。K表示共同好友数不少于K的两个用户才互相算作潜在好友。U表示需要输出标号为U的用户的潜在好友,对应矩阵行/列标号为U的节点,U从0开始计。
输入的第二行到第N+1行是用户之间的图的邻接矩阵:0代表不是好友,1代表是好友。

输入样例


1
2
3
4
5
6
7
6 1 3
0 1 0 1 0 1 
1 0 0 0 0 1 
0 0 0 0 0 1 
1 0 0 0 0 1 
0 0 0 0 0 1 
1 1 1 1 1 0

输出样例


1
1 2 4

提示

图的邻接矩阵对角线元素没有意义,且为对称阵。

我写的代码


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <bits/stdc++.h>
using namespace std;

struct peo {
    // idx, index; b, count
    int idx, count;
    peo(int a, int b) : idx(a), count(b) {}

    bool operator<(const struct peo& rhs) const {
        if (count > rhs.count)
            return true;
        if (count < rhs.count)
            return false;
        return idx < rhs.idx;
    }
};

int main() {
    ios::sync_with_stdio(false);

    int n, k, u;

    cin >> n >> k >> u;

    vector<peo> ans;

    bitset<5000> b[5000];

    for (int i = 0; i < n; ++i) {
        b[i].reset();
        for (int j = 0; j < n; ++j) {
            int k;
            cin >> k;
            if (k) {
                b[i].set(j);
            } else {
            }
        }
    }

    for (int i = 0; i < n; ++i) {
        if (i == u || b[u].test(i))
            continue;
        b[i] &= b[u];
        if (b[i].count() >= k)
            ans.emplace_back(peo(i, b[i].count()));
    }

    sort(ans.begin(), ans.end());

    if (!ans.empty()) {
        cout << ans[0].idx;
        for (int i = 1; i < ans.size(); ++i)
            cout << " " << ans[i].idx;
    }
    cout << endl;


    return 0;
}
最大的测试数据有到达4000+

原来并不是用位存的, 是用vector存的, 内存直接爆了, so…

Saturday, November 17, 2018

V2Ray + iptables 实现全局代理



设置全局代理的目的懒得烦那堵破墙
ALL_PROXY有一定的局限性, 所以还是需要全局代理舒服点
由于V2Ray迭代速度太快, 写上我现在使用的版本号 V2Ray 4.5.0 (Po) 20181116

V2Ray

思路是使用
iptables 将流量转发到 V2Ray 的透明代理上
具体如何实现参考V2Ray Dokodemo-door

iptables

没有了解过iptablesGoogle了解下
重点知道iptablesnat的是干啥的, 还有iptables的常用命令即可


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/sh

# 删除设置
# iptables -t nat -F
# iptables -t nat -X GLOBAL
#

# 新建一个`GLOBAL`链
iptables -t nat -N GLOBAL

# 添加链`GLOBAL`到链`OUTPUT`上
iptables -t nat -A OUTPUT -p tcp -j GLOBAL
iptables -t nat -A OUTPUT -p udp -j GLOBAL

# 忽略对你服务器地址的转发
iptables -t nat -A GLOBAL -d 这里写你服务器的地址 -j RETURN

# 忽略本地地址, 按自己的需求改写
iptables -t nat -A GLOBAL -d 127.0.0.1/8 -j RETURN
iptables -t nat -A GLOBAL -d 192.168.1.0/24 -j RETURN # 忽略本地局域网地址, 按自己局域网改
iptables -t nat -A GLOBAL -d 114.114.114.114 -j RETURN # 忽略DNS服务器地址

# 添加转发tcp, udp 到端口 1080, 这里端口写你在V2Ray中设置的端口
iptables -t nat -A GLOBAL -p tcp -j REDIRECT --to-ports 1080
iptables -t nat -A GLOBAL -p udp -j REDIRECT --to-ports 1080

# 最后显示设置
iptables -t nat -nvL

Tuesday, November 13, 2018

MacOS 默认群组之间的区别

本文讲解MacOS默认群组wheel admin staff everyone
wheel 是系统管理员组, 默认有用户root, 此组中的用户拥有系统最高权限, 100%的控制系统, wheel源于BSD UNIX, 而 wheel又有掌舵意思, 意味这掌控着系统方向
admin 是用户管理员组, 在此组中的成员可以通过sudo命令暂时升级为root去执行命令, 和wheel同样身为管理员, 但是在平时, 如果不使用sudo的话就和普通用户没什么区别, 安全性更好
staff 本机的用户都会在此组中, 注意, 并不包括用户guest
everyone 直译过来就是任何人, 包括任何用户, 比如guest或者是远程连接过来的用户

reference

Wednesday, November 7, 2018

Vim 替换基本命令讲解

使用Vim很长时间了, 我对于替换命令的印象还是最基本的这样:%s/pattern/string/g
所以写下本文是为了好好梳理一下, 本文只总结最常用的方法对于不常用或比较复杂的不进行介绍
本文基于Vim Docs, 想看官方文档的请在Vim中运行:h :s

基本格式

替换命令的基本格式是:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
我们可以分成
  • [range]
  • s[ubstitute]
  • {pattern}
  • {string}
  • [flags]
  • [count]
    来进行讲解

[range]

range太强大, 很多地方都可以用的到, 所以我单独写了一篇: Vim range详解

s[ubstitute]

这里的s[ubstitute]代表动作为替换, 由于substitute太长, 一般简写s即可

{pattern}

用来匹配的正则表达式

{string}

用来替换的内容
支持正则表达式的子匹配
  • \0 匹配到的字符串
  • \1 第一个子匹配
  • \2 第二个子匹配…以此类推
  • \r 换行
  • \b backspace
  • \t table
  • \\ \

[flags]

Options
  • c confirm, 每个匹配都可以选择替换还是不替换
    • y yes, 替换
    • l last, 替换并退出
    • n next, 跳过
    • a all, 替换此次和后面所有
    • q quit, 退出
  • g 对行内所有匹配, 如果没有这个标志, 默认只替换行内匹配的第一个
  • i ignore 忽略大小写
  • I 不忽略大小写
  • n 不进行替换, 只显示匹配成功的次数
  • p print, 显示最后一次匹配的行
  • # 类似p, 同时显示行号
  • l list, 类似p, 但显示方式类似于:list

[count]


替换的行数
默认为一行
如果[range]省略, 连光标那一行往下一共[count]行的范围
否则是[range]最后一行往下一共[count]行的范围