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; }
更正:输出的顺序保证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; }
更正:模数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; }
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; }
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; }