A.论如何出一道水题
签到题,注意下特殊情况

n=input()
n=int(n)
if n==1:
    print(2)
else:
    print(2*n-1)

B.暴力出奇迹
感觉好难想。。
这道题的方法是:按位把ai分解,然后,按照二进制位,纵向的看各个ai,若在一段中ai在某一位上都是1,那么,这一点"与运算"出来的结果也会是1,那么,我们就可以尝试下这个值是不是最大值(说简单点,就是一整段&之后去和ans取一个max),最后出来的结果就是最大值。
直接写完会有个疑虑:会不会存在一种情况,中间有个0,但是选出来的AND*SUM更大呢?这个得看其他位上的情况。若其他位上的这个位置都为0,那么很显然这一段是没有尝试的必要的,因为一&一下AND的值就成为0了。否则,这一段总会在纵向看某一位的时候被尝试到的。所以,这是一种贪心算法。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=1e5+10;
ll n;
ll a[maxn];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    //===========================================================
    read(n);
    ll ans=0;
    rep(i,1,n) read(a[i]);
    rep(j,0,18){
        ll sum=0,AND=a[1];
        rep(i,1,n){
            if((a[i]>>j)&1) AND&=a[i],sum+=a[i],ans=max(ans,AND*sum);
            else{
                AND=a[i+1];
                sum=0;
            }
        }
    }
    write(ans);
    //===========================================================
    return 0;
}

D.Cliques
这题看到数据范围应该就是要暴力的(但还是不会Orz)。
首先要理解好Cliques(团)这个概念,他指的是一个连通分量中每两个顶点都有一条相连的边(注意,是边,不是路径),因此,我们可以得到以下结论:在一个图中,如果两个点之间存在路径,则,与其中一个点相连的点肯定也需要和另一个点存在路径相连,这是我们走下去的依据。
这道题提供了两种操作:删除已存在边或增加本不存在的边。我们可以枚举任意两个点,若这两个点有直接的边相连,我们再去枚举第三个点,若这第三个点和这两个点都有边相连,则符合题意,无需操作。否则,需要操作。
我们可以考虑三种方法:
1、把第一、第二个点之间的边删掉,让他们不连通,就没有这个烦恼啦
2、把缺失的边给添加上,然后再递归一层dfs验证整个图是否符合题意。
3、把原本链接第三个点的边删掉,也是递归一层验证。
然后全局顶一个res去记录最小操作数就行了。
但是,这道题因为运算量很大,所以,题目给了我们限制:10次以上的算作无法完成,所以,每次递归到10次之后可以直接return,该更改方案不成立。
另外,如果在某一个递归中发现不符合题意,则可以直接break跳出循环,不用继续尝试,因为如果需要更新答案,下一层dfs已经更新好了,不能更新依旧不能更新,这一层没有再继续的必要。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
int e[105][105];
int n,t;
int res=11;
void dfs(int step){
    if(step>=res) return ;
    int flag=0;
    rep(i,1,n){
        rep(j,i+1,n){
            if(e[i][j]){
                rep(k,1,n){
                    if(i==k||j==k) continue;
                    if(!(e[i][k]^e[j][k])) continue;
                    flag=1;
                    e[i][j]^=1,e[j][i]^=1;
                    dfs(step+1);
                    e[i][j]^=1,e[j][i]^=1;

                    e[i][k]^=1,e[k][i]^=1;
                    dfs(step+1);
                    e[i][k]^=1,e[k][i]^=1;

                    e[j][k]^=1,e[k][j]^=1;
                    dfs(step+1);
                    e[j][k]^=1,e[k][j]^=1;
                    if(flag) break;
                }
            }
            if(flag) break;
        }
        if(flag) break;
    }
    if(!flag){
        res=min(res,step);
    }
    return ;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    //===========================================================
    read(t);
    int kase=0;
    while(t--){
        res=11;
        read(n);
        rep(i,1,n){
            rep(j,1,n){
                read(e[i][j]);
            }
        }
        dfs(0);
        if(res>=11){
            printf("Case #%d: %d\n",++kase,-1);
        }
        else{
            printf("Case #%d: %d\n",++kase,res);
        }
    }
    //===========================================================
    return 0;
}

E.跳石头
这道题写出来也是一波三折的。。
这道题的做法是二分验证答案。具体还是看代码吧,语言不好描述。。有点贪心的思路。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
//#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=5e4+10;
ll d[maxn];
ll n,m,l;
bool check(ll x){
    int cnt=0;
    int pre=0;
    rep(i,1,n){
        if(d[i]-d[pre]<x){
            cnt++;
        }
        else{
            pre=i;
        }
    }
    if(cnt<=m) return true;
    return false;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    //===========================================================
    read(l),read(n),read(m);
    rep(i,1,n) read(d[i]);
    d[n+1]=l;
    n++;
    ll l=0,r=1e9+7;
    while(l<=r){
        ll m=(l+r)>>1;
        if(check(m)){
            l=m+1;
        }
        else{
            r=m-1;
        }
    }
    write(l-1);
    //===========================================================
    return 0;
}

F.树上求和
这道题比较容易想。通过观察,我们会发现,树链和其实就是对每两个节点的组合都走一次。根据贪心思想,我们要是的权值和最小,只需要让经过次数最多的边权值小就行了。级数边被经过的次数,就是把这条边的两边看着两个连通块,这条边经过的次数就是两边的size的乘积。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
#define int ll
const int maxn=1e5+10;
struct Edge{
    int next,to;
}e[maxn<<1];
int n;
int head[maxn],cnt;
int si[maxn],si2[maxn];
int in[maxn];
void add(int x,int y){
    e[cnt].to=y;
    e[cnt].next=head[x];
    head[x]=cnt++;
}
void dfs(int u,int fa){
    si[u]=1;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v==fa) continue;
        dfs(v,u);
        si[u]+=si[v];
    }
    si2[u]=n-si[u];
}
vector<ll> num;
signed main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    //===========================================================
    read(n);
    memset(head,-1,sizeof(head));
    rep(i,2,n){
        int a,b;
        read(a),read(b);
        add(a,b),add(b,a);
        in[b]++;
    }
    int s=-1;
    rep(i,1,n){
        if(in[i]==0){
            s=i;
            break;
        }
    }
    dfs(s,-1);
    rep(i,1,n){
        if(si[i]*si2[i]!=0) num.push_back(si[i]*si2[i]);
    }
    sort(num.begin(),num.end(),greater<ll>());
    ll ans=0;
    rep(i,0,num.size()-1){
        ans+=num[i]*(i+1);
    }
    write(ans);
    //===========================================================
    return 0;
}