NOIP2011day2&&引水入城

13 篇文章 0 订阅
9 篇文章 0 订阅

factor:
题目大意:求(ax+by)^k展开后x^n*y^m的系数%10007。n,m,k<=1e3,a,b<=1e6.
题解:
裸的二项式定理,得到x^n*y^m的系数为 an bm Cmk ,组合数取模可以用逆元也可以用杨辉三角形。时间复杂度:O(k^2)(杨辉三角形)或O(k log 10007)(逆元),空间复杂度:O(k^2)(杨辉三角形)或O(1)(逆元)。
代码给的是杨辉三角形。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int a,b,k,n,m,i,j,f[1010][1010];
int ksm(int x,int y){
    int ans=1;
    for(;y;y>>=1){
        if(y&1)ans=((long long)ans*x)%10007;
        x=((long long)x*x)%10007;
    }
    return ans;
}
int main(){
    freopen("factor.in","r",stdin);
    freopen("factor.out","w",stdout);
    scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
    f[0][0]=1;
    for(i=1;i<=k;i++)
        for(j=0;j<=k;j++)
            f[i][j]=(f[i-1][j]+f[i-1][j-1])%10007;
    printf("%d",(((ksm(a,n)*ksm(b,m))%10007)*f[k][m])%10007);
    return 0;
}

qc:
突然想骗访问量……
http://blog.csdn.net/PbTfcLx/article/details/50493189
这是我以前写的题解……这里贴C++的代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int n,m,i,mid,li=1e7,ri,l[200010],r[200010],w[200010],v[200010],a[200010];
long long S,j,s[200010],ans=1e18;
long long pd(int x){
    long long ans=0;
    memset(a,0,sizeof(a));
    memset(s,0,sizeof(s));
    for(int i=1;i<=n;i++)
        if(w[i]>=x)s[i]=s[i-1]+v[i],a[i]=a[i-1]+1;
        else s[i]=s[i-1],a[i]=a[i-1];
    for(int i=1;i<=m;i++)
        ans+=(s[r[i]]-s[l[i]-1])*(a[r[i]]-a[l[i]-1]);
    return ans;
}
int main(){
    freopen("qc.in","r",stdin);
    freopen("qc.out","w",stdout);
    scanf("%d%d%I64d",&n,&m,&S);
    for(i=1;i<=n;i++)scanf("%d%d",&w[i],&v[i]),ri=max(ri,w[i]),li=min(li,w[i]);
    for(i=1;i<=m;i++)scanf("%d%d",&l[i],&r[i]);
    while(li<=ri){
        mid=(li+ri)>>1;
        j=pd(mid);
        ans=min(ans,abs(j-S));
        if(j>S)li=mid+1;
        else ri=mid-1;
    }
    printf("%I64d",ans);
    return 0;
}

bus:
嗯……以前我也写过题解……
http://blog.csdn.net/PbTfcLx/article/details/50493190

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
struct node{
    int la,xia,d;
}c[1010];
int n,m,k,a[10010],b[10010],t[10010],i,j,d[1010],maxn,maxi,ans,dat[1010];
int main(){
    freopen("bus.in","r",stdin);
    freopen("bus.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<n;i++)scanf("%d",&c[i].d);
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&t[i],&a[i],&b[i]);
        c[a[i]].la=max(c[a[i]].la,t[i]);
        c[b[i]].xia++;
    }
    for(i=2;i<=n;i++)d[i]=max(c[i-1].la,d[i-1])+c[i-1].d;
    for(;k;k--){
        maxn=maxi=0;
        for(i=n;i;i--)
            if(c[i].la<d[i])dat[i]=dat[i+1]+c[i].xia;
            else dat[i]=c[i].xia;
        for(i=1;i<=n;i++)
            if(dat[i]>maxn&&c[i-1].d>0)maxn=dat[i],maxi=i;
        c[maxi-1].d--;
        for(i=maxi;i<=n;i++)d[i]=max(d[i-1],c[i-1].la)+c[i-1].d;
    }
    for(i=1;i<=m;i++)ans+=d[b[i]]-t[i];
    printf("%d",ans);
    return 0;
}

flow:
题目大意:一个n*m的矩阵,第一行可以建蓄水厂,最后一行的每个格子都需要有水,每个格子可以可以由它旁边的海拔比它高的有水的格子输水过来,求是否能将最后一行的每个格子都输到水,若可以输出最少的蓄水厂数,若不行,输出不能输到水的格子数。n,m<=500.
题解:
我们需要先判断是否最后一行的每个格子全都能覆盖到……
这个只需要搜一遍就好了,还可以记忆化,就保证了复杂度为O(nm),对于某个格子,我们搜到它能流向的格子,然后如果该格子为最后一行的,我们就cnt++,最终只需判断cnt是否=n即可。
如果cnt

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
struct node{
    int l,r;
    bool friend operator <(node a,node b){
        if(a.l==b.l)return a.r>b.r;
        return a.l<b.l;
    }
}a[510][510];
int n,m,i,j,cnt,l,r,maxn,ans=1000,h[510][510],ff[510],dx[4]={0,1,-1,0},dy[4]={1,0,0,-1};
bool f[510][510],flag;
void dfs(int x,int y){
    if(x==n){
        a[x][y].l=min(a[x][y].l,y);
        a[x][y].r=max(a[x][y].r,y);
    }
    f[x][y]=1;
    for(int i=0;i<4;i++)
        if(x+dx[i]>0&&x+dx[i]<=n&&y+dy[i]>0&&y+dy[i]<=m){
            int fx=x+dx[i],fy=y+dy[i];
            if(h[x][y]>h[fx][fy]){
                if(!f[fx][fy])dfs(fx,fy),a[x][y].l=min(a[x][y].l,a[fx][fy].l),a[x][y].r=max(a[x][y].r,a[fx][fy].r);
                else a[x][y].l=min(a[x][y].l,a[fx][fy].l),a[x][y].r=max(a[x][y].r,a[fx][fy].r);
            }
        }
}
int main(){
    int __size__ = 20 << 20;
    char *__p__ = (char*)malloc(__size__) + __size__;
    __asm__("movl %0, %%esp\n" :: "r"(__p__));
    freopen("flow.in","r",stdin);
    freopen("flow.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)a[i][j].l=1000;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)scanf("%d",&h[i][j]);
    for(i=1;i<=m;i++)
        if(!f[1][i])dfs(1,i);
    flag=1;
    for(i=1;i<=m;i++)
        if(!f[n][i]){
            flag=0;
            cnt++;
        }
    if(!flag){
        puts("0");
        printf("%d",cnt);
    }
    else{
        puts("1");
        sort(a[1]+1,a[1]+1+m);
        memset(ff,1,sizeof(ff));
        ff[1]=1;
        for(i=2;i<=m;i++){
            maxn=1000;
            for(j=1;j<i;j++)
                if(a[1][j].r>a[1][i].l-2)maxn=min(maxn,ff[j]);
            ff[i]=maxn+1;
        }
        for(i=1;i<=m;i++)
            if(a[1][i].r==m)ans=min(ans,ff[i]);
        printf("%d",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值