51nod水题记
妈呀51nod已经刷不动了又开始跟bzoj一样总是得看题解了。。。那么发一下总结吧。。。
1051:最大子矩阵
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ll long long const int nmax=505; int read(){ int x=0,f=1;char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } ll a[nmax][nmax]; int main(){ int m=read(),n=read();ll ans=0,tot,tmp; rep(i,1,n) rep(j,1,m) a[i][j]=a[i-1][j]+read(); rep(i,1,n) rep(j,i,n) { tot=0; rep(k,1,m) { tmp=tot; tot+=a[j][k]-a[i-1][k]; if(tot<0) ans=max(ans,tmp),tot=0; ans=max(ans,tot); } } printf("%lld\n",ans); return 0; }
1013:等比数列求和+逆元就可以了。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define ll long long const ll mod=1000000007; int main(){ int n;scanf("%d",&n); ll tmp=3,ans=1;++n; while(n){ if(n&1) ans=ans*tmp%mod; tmp=tmp*tmp%mod;n>>=1; } printf("%lld\n",(ans-1)*500000004%mod); return 0; }
1021:石子归并O(n3)
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=105; int dp[nmax][nmax],a[nmax]; void mins(int &a,int b){ if(a>b) a=b; } int main(){ clr(dp,0x7f); int n=read();rep(i,1,n) a[i]=read()+a[i-1],dp[i][i]=0; rep(i,1,n-1) rep(j,1,n-i) { rep(k,j,j+i-1) mins(dp[j][j+i],dp[j][k]+dp[k+1][j+i]+a[j+i]-a[j-1]); } printf("%d\n",dp[1][n]); return 0; }
1268:O(2^20)爆搜。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int a[25],n,m; bool dfs(int cur,int sm){ if(sm==m||sm+a[cur]==m) return 1; if(cur>n) return 0; return dfs(cur+1,sm+a[cur])||dfs(cur+1,sm); } int main(){ scanf("%d%d",&n,&m); rep(i,1,n) scanf("%d",&a[i]); if(dfs(1,0)) printf("Yes\n");else printf("No\n"); return 0; }
1068:手推了一下发现110110110110。。。然后就可以了。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) const int nmax=1e3+5; char s[nmax]; int main(){ int n;scanf("%d",&n); rep(i,1,n) { scanf("%s",s); int len=strlen(s),ans=0; rep(j,0,len-1) ans+=s[j]-'0'; ans%3?printf("A\n"):printf("B\n"); } return 0; }
1099:usaco做过的那种sort贪心确定顺序的题。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e5+4; struct nd{ int x,y; bool operator<(const nd&rhs)const{ return x-y>rhs.x-rhs.y;} }; nd ns[nmax]; int main(){ int n=read(); rep(i,1,n) ns[i].x=read(),ns[i].y=read(); sort(ns+1,ns+n+1); int ans=0,cur=0; rep(i,1,n) ans=max(ans,cur+ns[i].x),cur+=ns[i].y; printf("%d\n",ans); return 0; }
1117:贪心每次拿最少的两个合并。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e4+5; struct nd{ int x; nd(int x):x(x){}; bool operator<(const nd&rhs) const{ return x>rhs.x;} }; priority_queue<nd>q; int main(){ int n=read(),u,v,ans=0; rep(i,1,n) u=read(),q.push(u); rep(i,1,n-1){ u=q.top().x;q.pop(); v=q.top().x;q.pop(); ans+=u+v;q.push(nd(u+v)); } printf("%d\n",ans); return 0; }
1267:4个数的和为0,n2排序一下扫一遍就可以了,sxt大爷是用map水过去的。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0,f=1;char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } const int nmax=1e3+5; const int maxn=1e6+5; int a[nmax]; struct node{ int a,b,c; bool operator<(const node&rhs) const{ return c<rhs.c;} }; node ns[maxn]; int main(){ int n=read(); rep(i,1,n) a[i]=read(); int u=0,v,d; rep(i,1,n-1) rep(j,i+1,n) ns[++u].a=i,ns[u].b=j,ns[u].c=a[i]+a[j]; sort(ns+1,ns+u+1); int l=1,r=u; while(l<=u){ if(!r) break; if(ns[l].c+ns[r].c==0){ if(ns[l].a!=ns[r].a&&ns[l].a!=ns[r].b&&ns[l].b!=ns[r].a&&ns[l].b!=ns[r].b){ printf("Yes\n");return 0; } if(ns[l].c==ns[l+1].c) ++l; else if(ns[r].c==ns[r-1].c) --r; else ++l,--r; }else if(ns[l].c+ns[r].c<0) ++l; else --r; } printf("No\n"); return 0; }
1163:usaco做过的贪心
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } struct node{ int a,b; bool operator<(const node&rhs)const{ return a<rhs.a;} }; node ns[50005]; struct edge{ int b; edge(int b):b(b){}; bool operator<(const edge&rhs)const{ return b>rhs.b;} }; priority_queue<edge>q; int main(){ int n=read(),u,v,d; rep(i,1,n) ns[i].a=read(),ns[i].b=read(); sort(ns+1,ns+n+1); int cnt=0;long long ans=0; rep(i,1,n){ if(cnt<ns[i].a) q.push(edge(ns[i].b)),++cnt,ans+=ns[i].b; else if((u=q.top().b)<ns[i].b) q.pop(),q.push(edge(ns[i].b)),ans+=ns[i].b-u; } printf("%lld\n",ans); return 0; }
1102:维护左边和右边能够到达的最大就可以了。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e4+5; int a[nmax],s[nmax],t[nmax]; int main(){ int n=read(); rep(i,1,n) a[i]=read(),s[i]=t[i]=i; rep(i,1,n) while(a[i]<=a[s[i]-1]&&s[i]>0) s[i]--; dwn(i,n,1) while(a[i]<=a[t[i]+1]&&t[i]<n) t[i]++; long long ans=0; rep(i,1,n) ans=max(ans,(long long)(t[i]-s[i]+1)*a[i]); printf("%lld\n",ans); return 0; }
1065:用set水过去了。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<set> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long ll read(){ ll x=0,f=1;char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } const int nmax=5e4+5; const ll inf=1e18; set<ll>s; int main(){ int n=read();ll cnt=0,ans=inf; set<ll>::iterator it;s.insert(-inf); rep(i,1,n) { cnt+=read(); it=s.lower_bound(cnt);--it; if(*it!=-inf) ans=min(ans,cnt-*it); if(cnt>0) ans=min(ans,cnt); s.insert(cnt); } printf("%lld\n",ans); return 0; }
1270:要么选最大值要么选最小值dp就可以了。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e4+5; int a[nmax]; int dp[nmax][2]; int main(){ int n=read(),u,v,d,tmp,temp; rep(i,1,n) a[i]=read(); rep(i,2,n){ dp[i][1]=max(dp[i-1][1]+abs(a[i-1]-a[i]),dp[i-1][0]+a[i]-1); dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i-1]-1); } printf("%d\n",max(dp[n][0],dp[n][1])); return 0; }
1393:+1-1然后乱搞。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) const int nmax=2e6+5; int a[nmax];char s[nmax]; int main(){ scanf("%s",s+1); int len=strlen(s+1),u=1e6,ans=0; rep(i,1,len) { if(s[i]=='0') --u;else ++u; if(a[u]||u==1e6) ans=max(ans,i-a[u]); else a[u]=i; } printf("%d\n",ans); return 0; }
1127:线性扫一下就可以了。。。r是递增的
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) const int nmax=1e5+5; const int inf=0x7f7f7f7f; char s[nmax]; int a[30]; int main(){ scanf("%s",s+1); int r=0,n=strlen(s+1),cnt=0,ans=inf; rep(i,1,n){ if(i!=1&&!--a[s[i-1]-'A']) --cnt; while(cnt<26&&r<n){ if(++a[s[++r]-'A']==1) ++cnt; } if(cnt!=26) break; ans=min(ans,r-i+1); } if(ans==inf) printf("No Solution\n"); else printf("%d\n",ans); return 0; }
1097:我只会用string水过去。。。好像usaco做过类似的题。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e4+5; struct node{ string s; bool operator<(const node&rhs)const { return s+rhs.s<rhs.s+s;} }; node a[nmax]; int main(){ int n=read(); rep(i,1,n) cin>>a[i].s; sort(a+1,a+n+1); string ans=a[1].s; rep(i,2,n) ans=ans+a[i].s; rep(i,0,ans.size()-1){ cout<<ans[i]; if((!((i+1)%1000))) printf("\n"); } if(ans.size()%1000) printf("\n"); return 0; }
1272:sort一下乱搞就可以了。。。标签是单调栈然后死想想不出来。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e4+5; struct node{ int a,b; bool operator<(const node&rhs)const { return a<rhs.a||a==rhs.a&&b<rhs.b;} }; node ns[nmax]; int main(){ int n=read(); rep(i,1,n) ns[i].a=read(),ns[i].b=i; sort(ns+1,ns+n+1); int u=ns[1].b,ans=0; rep(i,2,n){ if(ns[i].b>u) ans=max(ans,ns[i].b-u); else u=ns[i].b; } printf("%d\n",ans); return 0; }
1116:用到的性质不会证明不然的话就是也挺好写的。
//n*k%k-1=n%k-1*k%k-1=n%k-1; #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) const int nmax=1e5+5; char s[nmax]; int main(){ scanf("%s",s+1); int len=strlen(s+1),ans=0,mx=0,tmp; rep(i,1,len){ if(s[i]>='0'&&s[i]<='9') mx=max(mx,tmp=s[i]-'0'); else mx=max(mx,tmp=s[i]-'A'+10); ans+=tmp; } rep(i,mx+1,36) if(ans%(i-1)==0) { printf("%d\n",i);return 0; } printf("No Solution\n"); return 0; }
1770:总是WA了一个点过不了似乎是因为n-2并不是所有情况都一样!?! 而且我这样子写只适合于n<100的情况把。
/*#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } int cnt[11]; int main(){ int t=read(); while(t--){ int a=read(),b=read(),d=read(),n=read(); int u=a*b/10,v=a*b%10; if(u+v<=9) { if(!u){ if(d==v) printf("%d\n",n); else printf("0\n"); }else{ clr(cnt,0); cnt[u]++;cnt[v]++;if(n>1) cnt[u+v]+=n-1; printf("%d\n",cnt[d]); } }else{ clr(cnt,0); cnt[v]++;cnt[(u+v)%10]++;if(n>2) cnt[(u+v)%10+1]+=n-2;cnt[u+1]++; printf("%d\n",cnt[d]); } } return 0; }*/ #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } int main(){ int T=read(); while(T--){ int a=read(),b=read(),d=read(),n=read(); int ans=0,u=0,v=0,pre=-1,tmp; rep(i,1,n){ tmp=a*b+v;v=tmp/10;u=tmp%10; if(tmp==pre){ if(u==d) ans+=n-i+1; break; } pre=tmp; if(u==d) ans++; } if(v&&v==d) ans++; printf("%d\n",ans); } return 0; }
1179:这道题很明显是利用s[i]的范围来搞,时间复杂度是O(mxlnmx)差不多2000w的复杂度。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e6+5; int a[nmax]; int main(){ int n=read(),u,v,d,mx=0; rep(i,1,n) a[u=read()]++,mx=max(mx,u); dwn(i,mx,1){ if(a[i]>=2) { printf("%d\n",i);return 0; } d=a[i]; for(int j=i+i;j<=mx;j+=i){ if((d+=a[j])>=2){ printf("%d\n",i);return 0; } } } return 0; }
1070:斐波那契博弈。然而我看不懂证明。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=50; int a[nmax]; int main(){ a[0]=1;a[1]=1; rep(i,1,43) a[i]=a[i-1]+a[i-2]; int t=read(); while(t--){ int n=read(),f=-1; rep(i,1,45){ if(a[i]==n){ f=1;printf("B\n");break; } } if(f<0) printf("A\n"); } return 0; }
1491:神题。。我只知道他是斐波那契数列然后就不会了。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<cmath> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) const int nmax=1e5+5; char a[nmax],b[nmax]; int f[nmax]; int main(){ scanf("%s%s",a+1,b+1); int lena=strlen(a+1),lenb=strlen(b+1),len=max(lena,lenb); rep(i,1,lena) f[lena-i]=a[i]-'0'; rep(i,1,lenb) f[lenb-i]+='0'-b[i]; dwn(i,len,2) { if(f[i]<-1) { printf("<\n");return 0; }else if(f[i]>1){ printf(">\n");return 0; } f[i-1]+=f[i];f[i-2]+=f[i]; } f[1]+=f[2];f[0]+=f[2]; if(f[1]==0&&f[0]==0) { printf("=\n");return 0; } double u=(sqrt(5)+1)/2,ans=f[1]*u+f[0]; if(ans>0) printf(">\n");else printf("<\n"); return 0; }
1605:奇偶判断一下就好了。。。好像以前做过相似的。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) int main(){ int T;scanf("%d",&T); while(T--){ int n,m,u,cnt=0;scanf("%d%d",&n,&m); rep(i,1,n) rep(j,1,m) scanf("%d",&u),cnt+=u; if(cnt%2) printf("yadang\n"); else printf("xiawa\n"); } return 0; }
1412:很明显是利用树的深度来dp因为数据范围那样我能想到的只是这个了。。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long const ll mod=1e9+7; ll dp[2005][16]; int main(){ int n;scanf("%d",&n); dp[0][0]=dp[1][1]=1; rep(i,2,n) rep(j,2,15) rep(k,0,i-1) { (dp[i][j]+=dp[k][j-1]*dp[i-1-k][j-1])%=mod; (dp[i][j]+=2*dp[k][j-2]*dp[i-1-k][j-1])%=mod; } ll ans=0; rep(i,1,15) (ans+=dp[n][i])%=mod; printf("%lld\n",ans); return 0; }
1020:bzoj写过的神dp。。dp一个见过的优化技巧就是省掉一维!!!
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=2e4+5; const int mod=1e9+7; int dp[1005][nmax]; int main(){ rep(i,1,1000) dp[i][0]=1; rep(i,2,1000) { rep(j,1,min(i*(i-1)/2,20000)) { dp[i][j]=((ll)dp[i][j-1]+dp[i-1][j])%mod; if(j-i>=0) dp[i][j]=((ll)dp[i][j]-dp[i-1][j-i]+mod)%mod; } } int t=read(); while(t--){ int n=read(),k=read(); printf("%d\n",dp[n][k]); } return 0; }
1405:树形dp先求出size和子树节点的距离之和,再推出其他的节点到他的距离之和即可。好像写过啊qaq。。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e5+5; const int inf=0x7f7f7f7f; struct edge{ int to;edge *next; }; edge es[nmax<<1],*pt=es,*head[nmax]; void add(int u,int v){ pt->to=v;pt->next=head[u];head[u]=pt++; pt->to=u;pt->next=head[v];head[v]=pt++; } int size[nmax],n; ll f[nmax],g[nmax]; void dfs(int x,int fa){ size[x]=1; qwq(x) if(o->to!=fa) { dfs(o->to,x);size[x]+=size[o->to];f[x]+=f[o->to]+size[o->to]; } } void DFS(int x,int fa){ qwq(x) if(o->to!=fa){ g[o->to]=g[x]+n-size[x]+f[x]-f[o->to]-size[o->to]+size[x]-size[o->to]; DFS(o->to,x); } } int main(){ n=read();int u,v,d; rep(i,1,n-1) u=read(),v=read(),add(u,v); dfs(1,0);DFS(1,0); rep(i,1,n) printf("%lld\n",f[i]+g[i]); return 0; }
1105:看数据范围明显是nlogn的做法。二分一下。挺好想的一道题。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long ll read(){ ll x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e4+5; ll a[nmax],b[nmax],n,K; ll check(ll x){ ll sm=0,tp; dwn(i,n,1){ tp=lower_bound(b+1,b+n+1,(x-1)/a[i]+1)-b; sm+=n-tp+1; if(tp==n+1) break; } return sm; } int main(){ n=read(),K=read(); rep(i,1,n) a[i]=read(),b[i]=read(); sort(a+1,a+n+1);sort(b+1,b+n+1); ll l=a[1]*b[1],r=a[n]*b[n],mid,ans; while(l<=r){ mid=(l+r)>>1; if(check(mid)>=K) ans=mid,l=mid+1; else r=mid-1; } printf("%lld\n",ans); return 0; }
1103:容斥原理。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e4+5; int a[nmax],b[nmax]; int main(){ int n=read(),flag=0,u,sm=0; rep(i,1,n){ a[i]=read();sm=(sm+a[i])%n; if(flag) continue; if(!sm){ printf("%d\n",i); rep(j,1,i) printf("%d\n",a[j]); flag=1; } else if(!b[sm]) b[sm]=i; else{ int tp=b[sm]; printf("%d\n",i-tp); rep(j,tp+1,i) printf("%d\n",a[j]); flag=1; } } return 0; }
1040:欧拉函数。。。
//gcd(i,n)=x gcd(i/x,n/x)=1 phi(n/x)*x; #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long ll get(ll x){ ll ans=x; for(ll i=2;i*i<=x;i++){ if(x%i==0) ans=ans/i*(i-1); while(x%i==0) x/=i; } if(x!=1) ans=ans/x*(x-1); return ans; } int main(){ ll n;scanf("%lld",&n); long long ans=0; for(ll i=1;i*i<=n;i++){ if(n%i) continue; ans+=i*get(n/i); if(i*i!=n) ans+=(n/i)*get(i); } printf("%lld\n",ans); return 0; }
❤1632:线性求逆元然后递推出组合数。然而我真心看不懂题意的转化。。。
//c(n-1,m)=(n-1)!/m!(n-1-m)! c(n-1,m-1)=(n-1)!/(m-1)!(n-1-m+1)! c(n-1,m)=c(n-1,m-1)*inv[m]*(n-m) #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e5+5; const ll mod=1e9+7; ll inv[nmax]; int main(){ int n=read(),u,v; rep(i,1,n-1) u=read(),v=read(); inv[1]=1; rep(i,2,n) inv[i]=(mod-mod/i)*inv[mod%i]%mod; ll ans=1,tmp=1; rep(i,1,n-1){ tmp=tmp*(n-i)%mod*inv[i]%mod; ans=(ans+tmp*(i+1)%mod)%mod; } printf("%lld\n",ans); return 0; }
1419:推规律。
#include<cstdio> #define ll long long int main(){ ll n;scanf("%lld",&n); if(n<=2) printf("%d\n",n); else if(n&1) printf("%lld\n",n*(n-1)*(n-2)); else if(n%3) printf("%lld\n",n*(n-1)*(n-3)); else printf("%lld\n",(n-1)*(n-2)*(n-3)); return 0; }