Bestcoder #74 hdu 5635 hdu 5636 hdu 5637 hdu 5638

hdu 5635

题意:

Peter有一个字符串s=s1s2...sns=s_{1}s_{2}...s_{n}suffi=sisi+1...snnssii字符开头的后缀. Peter知道任意两个相邻的后缀的最长公共前缀ai=lcp(suffi,suffi+1)(1i<n).

现在给你数组aaa, Peter有多少个仅包含小写字母的字符串满足这个数组. 答案也许会很大, 你只要输出对109+7取模的结果即可.
n<=1e5,
分析:

因为后缀如果相同的话,从后往前有两种可能,一是递增的,而且相差1,二是如果不递增,那么一定是0。这两种情况分别处理一下,就ok了

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int mod=1e9+7;
const int N=1e5+5;
int a[N];
typedef long long ll;
int n;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i0;i--){
            if(a[i]==0){
                ans=ans*25%mod;
            }
            else if(a[i]==a[i+1]+1){
                continue;
            }
            else{
                flag=false;
                break;
            }
        }
        if(flag)printf("%d\n",ans);
        else printf("0\n");
    }
    return 0;
}


hdu 5636

题意:

有一条长度为nn的链. 节点iii+1i+1之间有长度为11的边. 现在又新加了3条边, 每条边长度都是1. 给出mm个询问, 每次询问两点之间的最短路.
分析:

如果想缩短两点之间距离,就要进过给出3条边,可以分别处理一下,经过一条边,两条边,三条边的情况。去最小值就好。


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int mod=1e9+7;
const int N=1e5+5;
typedef long long ll;
int n,m;
int a[6];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<6;i++)
            scanf("%d",&a[i]);
        ll ans=0;
        for(int i=1;i<=m;i++){
            int s,t;
            scanf("%d%d",&s,&t);
            int d=abs(s-t);
            for(int i=0;i<6;i++){
                int tmp=abs(a[i]-s)+1+abs(a[1^i]-t);
                if(tmp

hdu 5637

题意:

给出nn个整数, 对于一个整数xx, 你可以做如下的操作若干次:

  • 令x的二进制,你可以翻转其中一个位.
  • 令y是给出的其中一个整数, 你可以把x变为x⊕y, 其中\⊕表示位运算里面的异或操作.

现在有若干整数对(S, T), 对于每对整数你需要找出从S变成T的最小操作次数.

分析:

考虑到第一种操作是将某一位取反,而第二种操作是抑或一个数。

显然第一种操作也是可以通过抑或一个数得到的。比如:第i位取反,相当于抑或(1<这个数。于是就将n个数扩大到n+17就可以了,因为100000最多17位。

此外如果p^a^b^c...=q的话,那么a^b^c...=p^q。于是,只需要求出p^q至少需要几个数抑或而成就可以了。


#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5;
int n,m;
int a[N],dis[N];
bool vis[N];
void bfs()
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue q;
    q.push(0);
    vis[0]=1;
    dis[0]=0;
    while(!q.empty()){
        int t=q.front();
        q.pop();
        for(int i=0;idis[t]+1)dis[v]=dis[t]+1;
            if(!vis[v]){
                vis[v]=1;
                q.push(v);
            }
        }
    }
}
int main()
{
    int T;
    //cout<<(1<<16)<

题目:hdu 5638

题意

给一个DAG,然后让你最多删除k条边,使得这个图的拓扑序最小。

题解:

贪心的想一想,现在我扔出来的点是一定是入度小于等于k,且编号最小的点。

这个怎么做呢?

线段树内二分,或者直接优先队列就好了。线段树改天试试

参考博客:http://www.cnblogs.com/qscqesze/p/5246150.html


#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+5;
bool vis[N];
int in[N];
vectore[N];
int n,m,k;
void init()
{
    memset(vis,0,sizeof(vis));
    memset(in,0,sizeof(in));
    for(int i=0;i<=n;i++)e[i].clear();
}
int main()
{
    int T;
    //freopen("f.txt","r",stdin);
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        init();
        int u,v;
        for(int i=0;i,greater >p;
        for(int i=1;i<=n;i++){
            if(in[i]<=k)p.push(i),vis[i]=1;
           // cout<k){vis[t]=0;continue;}
            k-=in[t];
            ans=(ans+(ll)cnt*t%mod)%mod;
            cnt++;
            for(int i=0;i





你可能感兴趣的:(BestCoder,STL,最短路,拓扑排序,想法题)