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

  

posted @ 2016-09-09 20:28  BBChq  阅读(243)  评论(0编辑  收藏  举报