noip模拟7
新的阶乘
考虑从这个式子下手,怎么更优秀的求得答案。
那么我们只需要考虑对于区间 内的所有数,一个数的贡献就是质因数的个数 。
如果从每个数开始进行质因数分解,时间复杂度是 ,不能接受啊。
那么我们可以仿照埃筛的思想,对于每个质数,找到它的所有倍数,对那个数进行贡献,那思路就非常清晰了。
因为会有多个同样质因数的情况,所以需要对枚举的倍数进行拆分。
总时间复杂度约为 。
能过反正。
(据说这题是今年百度之星初赛的题,这么强吗?)
点击查看代码
#include<bits/stdc++.h> using namespace std; #define int long long int n; const int N=1e7+7; int ans[N]; bitset<N>vis; void calc() { for(int i=2;i<=n;i++) { if(!vis[i]) { for(int j=1;j*i<=n;j++) { vis[j*i]=1; int k=j*i; while(k%i==0) ans[i]+=(n-(j*i)+1),k/=i; } } } } void write(int x) { if(x>9) write(x/10); putchar(x%10+'0'); } signed main() { freopen("factorial.in","r",stdin); freopen("factorial.out","w",stdout); scanf("%lld",&n); calc(); int flag=0; printf("f(%lld)=",n); for(int i=1;i<=n;i++) { if(ans[i]==0) continue; if(flag)putchar('*'); if(ans[i]==1) write(i); else write(i),putchar('^'),write(ans[i]); flag=1; } return 0; }
博弈树
结论题。
如果在直径中点那么 获胜,否则 获胜。
点击查看代码
#include <bits/stdc++.h> #define int long long using namespace std; const int N=1e5+5; int head[N],ecnt{}; struct EDGE{ int nxt,to; }e[N<<2]; inline void add(int u,int v) { e[++ecnt].nxt=head[u]; head[u]=ecnt; e[ecnt].to=v; } int f[N],d[N]; int maxval{},maxpos; inline void dfs1(int u,int fa) { f[u]=fa,d[u]=d[fa] + 1; if(d[u]>maxval) maxval=d[u],maxpos=u; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue; dfs1(v,u); } } int dfn[N],cnt{}; inline void dfs2(int u,int fa) { if(fa==0) maxval=fa; f[u]=fa,d[u]=d[fa]+1; dfn[u]=++cnt; if(d[u]>maxval) maxval=d[u],maxpos=u; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue; dfs2(v,u); } } vector<int>zj; bool fnd=0; inline void dfs3(int u,int fa) { if(u==maxpos) { fnd=1;zj.push_back(u);return; } for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue; dfs3(v,u); if(fnd) {zj.push_back(u);return;} } } signed main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); int n,q;cin>>n>>q; for(int i=1;i<n;i++) { int u,v;cin>>u>>v; add(u,v),add(v,u); } dfs1(1,0); int rt=maxpos; dfs2(rt,0),dfs3(rt,0); int siz=zj.size(); int pos=0; if(siz%2==1) pos=zj.at(siz>>1); while(q--) { int u;cin>>u; if(pos==u) puts("Bob"); else puts("Alice"); } return 0; }
划分
其实很简单。我们考虑分两种情况讨论。
第一种是题目给的特殊性质,满足 。这种情况就是前 个空,,能插最多 个板,那么划分成 段的方案数就是 。
但是题目上说可以划分成大于等于 段,那总方案数就是 。
另一种情况,我们想到之前那个划分线段集合的题。那道题有一个贪心策略就是找 个单个的线段去确保答案最大。而这道题可以沿用这种策略。考虑选取一个长度为 的字典序最大的段,因为要保证最大的数的位数最多,这样才能使答案最大。其他 段就是单个的点。
然后,考虑到一个二进制数的最后一位可以更改,那么我们只需要使用哈希去匹配有多少长度为 的子串是和最大答案相匹配的,统计即为答案。
题目里有 hack 数据,你需要找一个较为优秀的模数去双哈希,要不然会有一个点卡住。
考虑有边界情况 ,这时候答案是 ,方案数为 。
顺便拿了最优解
点击查看代码
#include<bits/stdc++.h> using namespace std; #define int long long int n,k; const int N=2e6+5; char c[N]; const int mod=998244353; int mx=0; int ppow(int a,int b) { int res=1; while(b) { if(b&1) res=(res*a)%mod; a=(a*a)%mod,b>>=1; }return res; } int f[N],g[N]; void init() { f[0]=g[0]=1; for(int i=1;i<=n;i++)f[i]=(f[i-1]*i)%mod; g[n]=ppow(f[n],mod-2); for(int i=n-1;i>=1;i--)g[i]=(g[i+1]%mod*(i+1)%mod); } int getc(int a,int b) { return f[a]*g[a-b]%mod*g[b]%mod; } #define ull unsigned long long ull p=13331,p1=1313131; const ull md=20091119; ull hs[N],pp[N]; ull hs1[N],pp1[N]; signed main() { // freopen("C-ex-2.in","r",stdin); freopen("divide.in","r",stdin); freopen("divide.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>k; cin>>(c+1); if(n==k) { int ccnt=0; for(int i=1;i<=n;i++) ccnt+=(c[i]=='1'); return cout<<ccnt<<" 1",0; } bool _=1; for(int i=1;i<=k;i++) _&=(c[i]=='0'); if(_) { int ans=0; for(int i=k+1;i<=n;i++) ans=((ans*2ll)%mod+c[i]-'0')%mod; init(); int ans2=0,cnt=0; for(int i=1;i<=n;i++) { if(c[i]=='1')break; ++cnt; } if(cnt==n)--cnt; for(int i=k-1;i<=cnt;i++)ans2=(ans2+getc(cnt,i))%mod; cout<<ans%mod<<" "<<ans2%mod<<"\n"; return 0; } int len=n-k+1; int mxpos=1; for(int i=1;i+len-1<=n;i++) { int j=i+len-1; int now=mxpos-1; bool flag=0; for(int k=i;k<=j;k++) { now++; if(c[k]==c[now])continue; if(c[k]>c[now]) {flag=1;break;} else break; } if(flag) mxpos=i; } // cout<<mxpos; int ans1=0; for(int i=mxpos;i<=mxpos+len-1;i++) ans1=(ans1*2)%mod+c[i]-'0'; for(int i=1;i<mxpos;i++) ans1=(ans1+c[i]-'0')%mod; for(int i=mxpos+len;i<=n;i++) ans1=(ans1+c[i]-'0')%mod; cout<<ans1<<" "; ull cmp=0,cmp1=0;pp[0]=1,pp1[0]=1; for(int i=1;i<=n;i++) { hs[i]=hs[i-1]*p+(int)c[i]; pp[i]=pp[i-1]*p; hs1[i]=hs1[i-1]*p1%md+(int)c[i]; hs1[i]%=md; pp1[i]=pp1[i-1]*p1%md; } int ans2=0; for(int i=mxpos;i<mxpos+len-1;i++) cmp=cmp*p+(int)c[i]; for(int i=mxpos;i<mxpos+len-1;i++) cmp1=cmp1*p1%md+(int)c[i],cmp1%=md; cmp1%=md; for(int i=1;i+len-1<=n;i++) { ull now=hs[i+len-2]-hs[i-1]*pp[len-1]; ull now2=((hs1[i+len-2]-hs1[i-1]*pp1[len-1]%md+md)%md+md)%md; if(now==cmp&&now2==cmp1)++ans2,ans2%=mod; } cout<<ans2; return 0; } /* 21 3 10010101010101110011111 10 6 0000000000 */
灯笼
你会吗?我不会。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!