51nod水题记

时间:2023-01-10 03:35:46

妈呀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;
}