noip模拟13
A. 工业题 / a
这里是由于数组开小了然后爆挂 40pts 的瑟瑟..
一道简单的推规律..
这里再次强调:数论部分的数学题有的时候真的就是把推理过程写得详细一点就可以爆切的!!!
#include<bits/stdc++.h> using namespace std; #define ll long long int #define lf double #define mp make_pair const ll mod=998244353; const ll N=8e5+50; inline void read(ll &ss) { ss=0; bool cit=0; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=1; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); if(cit) ss=-ss; } ll n,m,x,y,ans; ll f[N+50],g[N+50]; ll f1[N+50],f2[N+50]; ll add[N+100]; ll ksm(ll a,ll b,ll c) { ll temp=1; a%=c; while(b) { if(b&1) temp=(temp*a)%c; a=(a*a)%c; b>>=1; } return temp%mod; } ll C(ll a,ll b) { if(b>a) return 1; if(b==0) return 1; ll temp=(add[a]*ksm(add[a-b],mod-2,mod))%mod; temp=(temp*ksm(add[b],mod-2,mod))%mod; return temp%mod; } signed main() { read(n); read(m); read(x); read(y); x%=mod; y%=mod; f[0]=1,g[0]=1,ans=0,add[0]=1; for(ll i=1;i<=n;i++) read(f1[i]); for(ll j=1;j<=m;j++) read(f2[j]); for(ll i=1;i<=N;i++) add[i]=(add[i-1]*i)%mod; for(ll i=1;i<=n+m+1;i++) f[i]=(f[i-1]*x)%mod; // a 的 i 次幂 for(ll i=1;i<=n+m+1;i++) g[i]=(g[i-1]*y)%mod; // b 的 i 次幂 ll tmp,temp; for(ll i=1;i<=n;i++) { temp=f1[i]%mod; temp=(temp*f[m])%mod; temp=(temp*g[n-i])%mod; tmp=C(n-i+m-1,n-i); temp=(temp*tmp)%mod; ans=(ans+temp)%mod; } for(ll i=1;i<=m;i++) { temp=f2[i]%mod; temp=(temp*g[n])%mod; temp=(temp*f[m-i])%mod; tmp=C(m-i+n-1,m-i); temp=(temp*tmp)%mod; ans=(ans+temp)%mod; } printf("%lld",ans%mod); return 0; }
B. 卡常题 / b
看到题面以为知识超出了自己目前的所学范围了,以为随便水水就走掉这道题就可以了..
最后发现这是一道树形dp..
所以请屏幕前的您,不要因为题目的狐假虎威就选择了退缩或畏惧,这里引用 lbw (此非彼)关于高考的一句名言:
高考题都是大学老师出的,但是考的都是高中知识。高考讲究高起点、低落点..
我们可以选择把 y 和 y 的黑边和白边看成一条边,所以图中就只剩下 n 条边了,也就是一棵树上挂了一个环..
然后我们把环拆开,于是这道题就变成了《没有上司的舞会》..
#include<bits/stdc++.h> using namespace std; #define ll int #define lf double #define mp make_pair #define lb lower_bound const ll N=1e7+50; inline void read(ll &ss) { ss=0; bool cit=0; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=1; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); if(cit) ss=-ss; } ll n,cnt,ts; ll cut1,cut2,val1,val2; ll head[N],vis[N],dw[N],db[N]; ll f[N][2]; struct I { ll u,v,w,nxt; } a[N]; inline void add(ll u,ll v) { a[++ts].u=u; a[ts].v=v; a[ts].nxt=head[u]; head[u]=ts; } void dfs_ccl(ll now,ll dad) { vis[now]=1; for(ll i=head[now];i;i=a[i].nxt) { if(a[i].v==dad) continue; if(vis[a[i].v]) { cut1=a[i].v; cut2=now; continue; } dfs_ccl(a[i].v,now); } } ll dfs_tree(ll now,ll dad,ll father) { if(!dad) { if(f[now][1]) return f[now][1]; f[now][1]=db[now]*val1+dw[now]*val2; for(ll i=head[now];i;i=a[i].nxt) { if(a[i].v==father or (now==cut1 and a[i].v==cut2) or (now==cut2 and a[i].v==cut1)) continue; f[now][1]+=dfs_tree(a[i].v,1,now); } return f[now][1]; } else { if(!f[now][1]) { f[now][1]=db[now]*val1+dw[now]*val2; for(ll i=head[now];i;i=a[i].nxt) { if(a[i].v==father or (now==cut1 and a[i].v==cut2) or (now==cut2 and a[i].v==cut1)) continue; f[now][1]+=dfs_tree(a[i].v,1,now); } } if(!f[now][0]) { for(ll i=head[now];i;i=a[i].nxt) { if(a[i].v==father or (now==cut1 and a[i].v==cut2) ) continue; f[now][0]+=dfs_tree(a[i].v,0,now); } } return min(f[now][1],f[now][0]); } } signed main() { read(n); read(val1); read(val2); ll u,v; for(ll i=1;i<=n;i++) { read(u); read(v); add(u,v); add(v,u); db[u]++; dw[v]++; } dfs_ccl(1,0); ll ans; ans=dfs_tree(cut1,0,0); memset(f,0,sizeof f); ans=min(dfs_tree(cut2,0,0),ans); cut1=0,cut2=0; memset(vis,0,sizeof vis); memset(f,0,sizeof f); dfs_ccl(2,0); ans=dfs_tree(cut1,0,0); memset(f,0,sizeof f); ans=min(dfs_tree(cut2,0,0),ans); printf("%d",ans); return 0; }
C. 玄学题 / c
又是一道数学题..线性筛yyds..
#include<bits/stdc++.h> using namespace std; #define ll long long int #define lf double #define mp make_pair const ll N=1e7+50; inline void read(ll &ss) { ss=0; bool cit=0; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=1; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); if(cit) ss=-ss; } ll n,m,cnt1,cnt2,cnt; ll f[N],vis[N]; signed main() { read(n); read(m); ll ans=0; for(ll i=1;i*i<=n;i++) f[i*i]=1,vis[i*i]=1; for(ll i=1;i*i<=n;i++) { for(ll j=1;j*i*i<=n;j++) { if(!vis[j*i*i]) f[j*i*i]=j; } } ll temp=1; for(ll i=1;i<=n;i++) { temp=sqrt(m/f[i]); if(temp&1) ans--; else ans++; } printf("%lld",ans); return 0; } /* S1: 4 5 0 S2: 799 8278 */