qbxt十一系列四

关于考试:题目很难,T1和T3都失误,爆零orz

更正:第三组:不存在相同的字符|str|=26,26<=n<=100

【题目分析】

第一反应,组合数学;第二反应,有端倪;jn给了一道题GT考试 很多大神都做过,kmp+矩阵乘法

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+7;
const int mod=1e9+7;
int n,cnt,len;
char str[N],pat[N];
ll f[N];
void dfs(int now){
    if(now==n){
        if(++cnt>=mod) cnt%=mod;
        return ;
    }
    bool flag=(now<len-1)|(!equal(str+now-len+1,str+now,pat));
    for(char x='a';x<='z';x++){
        if(!flag&&x==pat[len-1]) continue;
        str[now]=x;
        dfs(now+1);
    }
}
ll fpow(ll a,ll p){
    ll res=1;
    for(;p;p>>=1,a=a*a%mod) if(p&1) res=res*a%mod;
    return res;
}
int main(){
    freopen("helloworld.in","r",stdin);
    freopen("helloworld.out","w",stdout);
    while(scanf("%d",&n)==1){
        scanf("%s",pat);
        len=strlen(pat);
        cnt=0;
        if(!n){puts("0");continue;} 
        if(n<=5){
            dfs(0);
            printf("%d\n",cnt);
        }
        else if(len==1){
            printf("%d\n",fpow(25,n));
        }
        else{
            f[0]=1;
            for(int i=1;i<=len;i++) f[i]=f[i-1]*26%mod;
            for(int i=len;i<=n;i++) f[i]=(f[i-1]*26-f[i-len]+mod)%mod;
            printf("%d\n",(int)f[n]);
        }
    }
    return 0;
}

更正:输出的顺序保证a<b

更正:输出样例:0 1000000006

【题目分析】

    矩阵乘法斐波那契数列变形

#include<cstdio>
#include<cstring>
#include<iostream>
#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif
using namespace std;
#define ll long long
#define N 3
const ll mod=1e9+7;
ll a[N][N],b[N][N],c[N][N];
ll p,q,a1,a2,n;
inline const ll read(){
    register ll x=0,f=1;
    register char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void work(){
    a[1][1]=0;a[1][2]=q;a[2][1]=1;a[2][2]=p;
    b[1][1]=0;b[1][2]=q;b[2][1]=1;b[2][2]=p;
    while(n){
        if(n&1){
            for(int i=1;i<=2;i++){
                for(int j=1;j<=2;j++){
                    for(int k=1;k<=2;k++){
                        c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod)%mod;
                    }
                }
            }
            memcpy(a,c,sizeof c);
            memset(c,0,sizeof c);
        }
        for(int i=1;i<=2;i++){
            for(int j=1;j<=2;j++){
                for(int k=1;k<=2;k++){
                    c[i][j]=(c[i][j]+b[i][k]*b[k][j]%mod)%mod;
                }
            }
        }
        memcpy(b,c,sizeof c);
        memset(c,0,sizeof c);
        n>>=1;
    }
}
int main(){
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
    p=1;q=1;a1=1;a2=2;
    n=read();ll bf=n;
    if(n==1){printf("1 1");return 0;}
    if(n%mod==0){printf("1 ");printf(LL,n-1);return 0;}
    n-=1;
    work();
    ll ans1=(a[1][1]%mod+a[2][1]%mod)%mod;
    n=bf;
    work();
    ll ans2=(a[1][1]%mod+a[2][1]%mod)%mod;
    if(ans1>ans2) swap(ans1,ans2);
    printf(LL,ans1);putchar(' ');printf(LL,ans2);
    return 0;
}

 

更正:模数1000000007

【题目分析】

    开始打了匈牙利算法,自我感觉p==1的情况还是可以混过去的吧,结果爆零啦

    考完据shenben和ylf说并不是匈牙利算法!!是树形DP!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 100010
#define mod 1000000007
#define ll long long
using namespace std;
ll T,P,n,head[maxn],num,f[maxn][2],g[maxn][2],L,R[maxn],l,r[maxn],son[maxn];
struct node{
    ll v,pre;
}e[maxn*2];
ll init(){
    ll x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='0')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
void Add(ll from,ll to){
    num++;e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
void Clear(){
    num=0;
    memset(f,0,sizeof(f));
    memset(g,0,sizeof(g));
    memset(head,0,sizeof(head));
}
void DP(ll now,ll from){
    g[now][0]=1;
    ll mx,sum;
    for(int i=head[now];i;i=e[i].pre){
        ll v=e[i].v;
        if(v==from)continue;
        DP(v,now);//x不连儿子 儿子们可连可不连 
        mx=max(f[v][1],f[v][0]);sum=0;
        if(mx==f[v][1])sum+=g[v][1];
        if(mx==f[v][0])sum+=g[v][0];
        g[now][0]=g[now][0]*sum%mod;
        f[now][0]+=mx;
    }
    //x连某个儿子 这个不选 其他的连或者不连 
    L=0;l=1;ll S=0;
    for(int i=head[now];i;i=e[i].pre) 
        if(e[i].v!=from)son[++S]=e[i].v;
    R[S+1]=0;r[S+1]=1;
    for(int i=S;i>=1;i--){
        ll v=son[i];sum=0;
        mx=max(f[v][1],f[v][0]);
        if(mx==f[v][1])sum+=g[v][1];
        if(mx==f[v][0])sum+=g[v][0];
        R[i]=R[i+1]+mx;
        r[i]=r[i+1]*sum%mod;
    }
    for(int i=1;i<=S;i++){
        ll v=son[i];
        mx=L+f[v][0]+R[i+1]+1;
        if(mx>f[now][1]){
            f[now][1]=mx;
            g[now][1]=l*g[v][0]%mod*r[i+1]%mod;
        }
        else if(mx==f[now][1])
            g[now][1]=(g[now][1]+l*g[v][0]%mod*r[i+1]%mod)%mod;
        sum=0;
        mx=max(f[v][1],f[v][0]);
        if(mx==f[v][1])sum+=g[v][1];
        if(mx==f[v][0])sum+=g[v][0];
        l=l*sum%mod;L+=mx;
    }
}
int main()
{
    freopen("hungary.in","r",stdin);
    freopen("hungary.out","w",stdout);
    T=init();P=init();
    while(T--){
        n=init();
        ll u,v;Clear();
        for(int i=1;i<n;i++){
            u=init();v=init();
            Add(u,v);Add(v,u);
        }
        DP(1,0);ll sum,mx;
        mx=max(f[1][0],f[1][1]);sum=0;
        if(mx==f[1][0])sum+=g[1][0],sum%=mod;
        if(mx==f[1][1])sum+=g[1][1],sum%=mod;
        if(P==1)cout<<mx<<endl;
        if(P==2)cout<<mx<<" "<<sum<<endl;
    }
    return 0;
}

 

 【题目分析】

    不会

#include<cstdio>
using namespace std;
const int N=205;
const int inf=0x3f3f3f3f;
inline int max(int a,int b){return a>b?a:b;} 
inline const int read(){
    register int x=0,f=1;
    register char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m;
int f[N][N];
int main(){
    freopen("radius.in","r",stdin);
    freopen("radius.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=inf;
    for(int i=1,x,y,z;i<=m;i++){
        x=read();y=read();z=read();
        if(f[x][y]>z) f[y][x]=f[x][y]=z;
    }
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i!=j&&j!=k&&i!=k){
                    if(f[i][j]>f[i][k]+f[k][j]){
                        f[i][j]=f[i][k]+f[k][j];
                    }
                }
            }
        }
    }
    int d=0;
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            if(f[i][j]!=inf) d=max(d,f[i][j]);
        }
    }
    double ans=d/2.0;
    printf("%.2lf",ans);
    return 0;
}

 

posted @ 2016-10-06 19:53  [lemon]  阅读(210)  评论(0编辑  收藏  举报
……