hdu 5635
题意:
Peter有一个字符串s=s1s2...sns=s_{1}s_{2}...s_{n}令suffi=sisi+1...snn是ss第ii字符开头的后缀. Peter知道任意两个相邻的后缀的最长公共前缀ai=lcp(suffi,suffi+1)(1≤i<n). 现在给你数组aaa, Peter有多少个仅包含小写字母的字符串满足这个数组. 答案也许会很大, 你只要输出对109+7取模的结果即可. n<=1e5,分析:
因为后缀如果相同的话,从后往前有两种可能,一是递增的,而且相差1,二是如果不递增,那么一定是0。这两种情况分别处理一下,就ok了
#include
#include
#include
#include
#include
#include
#include
#include
hdu 5636
题意:
有一条长度为nn的链. 节点ii和i+1i+1之间有长度为11的边. 现在又新加了3条边, 每条边长度都是1. 给出mm个询问, 每次询问两点之间的最短路.分析:
如果想缩短两点之间距离,就要进过给出3条边,可以分别处理一下,经过一条边,两条边,三条边的情况。去最小值就好。
#include
#include
#include
#include
#include
#include
#include
#include
hdu 5637
题意:
给出nn个整数, 对于一个整数xx, 你可以做如下的操作若干次:
现在有若干整数对(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