10.6 noip模拟试题

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

60

/*
呵呵哒~这题
正解还在研究....
因为没有题解只有个std还在看
不过乱搞一下可以70(数据好像有问题只有60)
首先一个字母的不说了
n<=5的暴力 不过吧 卡纯暴力
+个小小的剪枝就是只找危险串的前len-1位
最后一位枚举的时候判一下 这样能快一点
另外%30没有重复的串的话dp一下
f[i]表示前i位的方案数 先不考虑不合法的
那就是26^i 再减去f[i-len]就是说除了那len位危险的
剩下的有几种
正解好像巧妙用fail数组+位数dp 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
#define ll long long
using namespace std;
ll n,len,f[100010];
char s[100010],D[100010];
bool vis[100010];
long long ans;
void Dfs(int step)
{
    if(step==n+1){
        ans++;
        if(ans>=mod) ans%=mod;
    }
    else{
        bool flag=(step<len-1)||(!equal(s+step-len+1,s+step,D));
        for(char x='a'; x<='z'; x++){
            if(!flag&&x==D[len-1]) continue;
            s[step]=x;Dfs(step+1);
        }
    }
}
void Solve(){
    if(n==0)ans=0;
    else Dfs(1);
    cout<<ans<<endl;
}
void DP(){
    memset(f,0,sizeof(f));
    f[0]=1;
    for(int i=1;i<=n;i++){
        f[i]=f[i-1]*26%mod;
        if(i>=len)f[i]=((f[i]-f[i-len])%mod+mod)%mod;
    }
    cout<<f[n]<<endl;
}
int main()
{
    freopen("helloworld.in","r",stdin);
    freopen("helloworld.out","w",stdout);
    while(cin>>n){
        scanf("%s",D);len=strlen(D);
        ans=0;memset(vis,0,sizeof(vis));
        int sum=0;
        if(n<=5){
            Solve();continue;
        }
        for(int i=0;i<len;i++){
            if(vis[D[i]-'a']==0)sum++;
            vis[D[i]-'a']=1;
        }
        if(sum==len){
            DP();continue;
        }
        if(len==1){
            ans++;
            for(int i=1;i<=n;i++)ans=ans*25%mod;
            cout<<ans<<endl;continue;
        }
    }
    return 0;
}
View Code

 

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

更正:输出样例:0 1000000006

/*读错题目 把a+b的min输出来了QAQ*/
#include<iostream>
#include<cstdio>
#define mod 1000000007
#define ll long long
using namespace std;
ll k,a[2][2],f[2][2];
void mul(ll a[2][2],ll b[2][2]){
    ll c[2][2];c[0][0]=c[0][1]=c[1][0]=c[1][1]=0;
    for(ll i=0;i<2;i++)
        for(ll j=0;j<2;j++)
            for(ll k=0;k<2;k++)
                c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod)%mod;
    for(ll i=0;i<2;i++)
        for(ll j=0;j<2;j++)
            a[i][j]=c[i][j];
}
int main()
{
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
    cin>>k;
    if(k==1){
        cout<<"1 1"<<endl;
        return 0;
    }
    a[0][0]=a[0][1]=a[1][0]=1;
    f[0][0]=3;f[0][1]=2;
    k-=2;
    while(k){
        if(k&1)mul(f,a);
        k>>=1;mul(a,a);
    }
    cout<<f[0][1]<<" "<<f[0][0]<<endl;
    return 0;
}
View Code

 

更正:模数1000000007

50

/*
乱搞...
不会统计方案数 0...0
用匈牙利搞一下P==1的情况
还有几个点是暴力的 这样可以50分 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
#define mod 1000000007
using namespace std;
int T,P,n,head[maxn],num,f[maxn],match[maxn],ans,sum,C[maxn];
struct node{
    int v,pre;
}e[maxn*2];
struct edge{
    int u,v;
}c[maxn];
void Add(int from,int to){
    num++;e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
int Dfs(int u){
    for(int i=head[u];i;i=e[i].pre){
        int v=e[i].v;
        if(f[v])continue;f[v]=1;
        if(match[v]==0||Dfs(match[v])){
            match[v]=u;return 1;
        }
    }
    return 0;
}
void Mx(){
    for(int i=1;i<=n;i++)if(C[i]){
        memset(f,0,sizeof(f));
        ans+=Dfs(i);
    }
    if(P==1)printf("%d\n",ans);
    if(P==2)printf("%d 1\n",ans);
}
void dfs(int now,int s){
    if(now==n){
        if(s>ans){
            ans=s;sum=1;
        }
        else if(s==ans)sum++,sum%=mod;
        return;
    }
    if(f[c[now].u]==0&&f[c[now].v]==0){
        f[c[now].u]=1;f[c[now].v]=1;
        dfs(now+1,s+1);
        f[c[now].u]=0;f[c[now].v]=0;
    }
    dfs(now+1,s);
}
void Mxx(){
    dfs(1,0);
    printf("%d %d\n",ans,sum);
}
void Go(int now,int from){
    C[now]=!C[from];
    for(int i=head[now];i;i=e[i].pre){
        int v=e[i].v;
        if(v!=from)Go(v,now);
    }
}
int main()
{
    freopen("hungary.in","r",stdin);
    freopen("hungary.out","w",stdout);
    scanf("%d%d",&T,&P);
    while(T--){
        num=0;ans=0;sum=0;
        memset(f,0,sizeof(f));
        memset(head,0,sizeof(head));
        memset(match,0,sizeof(match));
        scanf("%d",&n);
        int u,v;
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            Add(u,v);Add(v,u);
            c[i].u=u;c[i].v=v;
        }
        Go(1,0);
        if(P==1||n>=1000){Mx();continue;}
        if(P==2){Mxx();continue;}
    }
    return 0;
}
View Code

100

/*
正解树形dp
忽略的他是棵 树 树 树.....
f[i][0 1]表示有没有连i的儿子
然后顺便统计方案数.... 
*/
#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;
}
View Code

 

 

 

 60

/*
正解还在看....这尼玛考试不发题解不讲解
就给个std看啊看看啊看 蒟蒻表示压力很大啊
这题乱搞的 有bug 似乎改不了了....
60 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 210
#define inf 1000000000
using namespace std;
int n,m;
double g[maxn][maxn],ans=inf;
struct node{
    int u,v;
    double t;
}e[maxn*100];
void Floyed(){
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(g[i][k]+g[k][j]<g[i][j])
                    g[i][j]=g[i][k]+g[k][j];
}
void Solve(){
    for(int k=1;k<=m;k++){
        int u=e[k].u,v=e[k].v;
        double t=e[k].t;
        double r1=0,r2=0;
        for(int i=1;i<=n;i++){
            if(g[i][u]>g[i][v]){
                if(r1<g[i][v])r1=g[i][v];
            }
            if(g[i][u]<g[i][v]){
                if(r2<g[i][u])r2=g[i][u];
            }
            if(g[i][u]==g[i][v]){
                double tmp=g[i][u];
                if(r1<r2&&r2<tmp)r2=tmp;
                if(r1>r2&&r1<tmp)r1=tmp;
            }
        }
        double r=r1+r2+t;r=r/2.0;
        double R;
        if(r>=r1&&r<=r1+t)R=r;
        else if(r<r1)R=r1;
        else R=r2;
        if(R<ans)ans=R;
    }
}
int main()
{
    freopen("radius.in","r",stdin);
    freopen("radius.out","w",stdout);
    scanf("%d%d",&n,&m);
    int u,v;double t;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            g[i][j]=inf;
    for(int i=1;i<=m;i++){
        scanf("%d%d%lf",&u,&v,&t);
        if(t<g[u][v])g[u][v]=t;
        if(t<g[v][u])g[v][u]=t;
        e[i].u=u;e[i].v=v;e[i].t=t;
    }
    for(int i=1;i<=n;i++)g[i][i]=0;
    Floyed();Solve();
    printf("%.2f\n",ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/yanlifneg/p/5935032.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值