• CF449 (Div. 1简单题解)


    A .Jzzhu and Chocolate

    pro:现在给定一个大小为N*M的巧克力,让你横着或者竖着切K刀,都是切的整数大小,而且不能切在相同的地方,求最大化其中最小的块。 (N,M,K<1e9)

    sol:如果横着切X刀,竖着切Y刀,那么最小的面积=(N/(X+1))*(M/(Y+1));一看这个公式知道是整数分块了,相同的部分合并。 需要保证X<N,Y<M;

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int N,M,K;ll ans=-1;
    int main()
    {
        scanf("%d%d%d",&N,&M,&K); K+=2;
        for(int i=1,j;i<=min(K-1,N);i=j+1){
            j=N/(N/i);int p=j;if(p>=K) p=K-1;
            if(K-p>M) continue;
            ans=max(ans,1LL*(N/i)*(M/(K-p)));
        }
        printf("%lld
    ",ans);
        return 0;
    }

    B .Jzzhu and Cities

    pro:给定N个城市, 1号是首都,M条双向带权公路,K条铁路,铁路直接连接首都和城市, 现在问最多可以删去多少铁路,使得首都到任意城市的最短路不变.

    sol:求最短路,如果铁路比最短路长,显然可以删去; 如果等于最短路,而最短路来源不唯一,那么显然也可以删去。 统计的时候记得至少留一个入度为1的。

    #include<bits/stdc++.h>
    #define ll long long
    #define pii pair<ll,int>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    const ll inf=1e18;
    using namespace std;
    const int maxn=1000010;
    int a[maxn],b[maxn],ind[maxn];ll dis[maxn],vis[maxn];
    int Laxt[maxn],Next[maxn],To[maxn],Len[maxn],cnt,N;
    void add(int u,int v,int w)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
    }
    void SPFA()
    {
        rep(i,2,N) dis[i]=inf;
        priority_queue<pii>q;
        q.push(pii(0LL,1));
        while(!q.empty()){
            int u=q.top().second; q.pop(); vis[u]=0;
            for(int i=Laxt[u];i;i=Next[i]){
                int v=To[i];
                if(dis[v]==dis[u]+Len[i]) ind[v]++;
                else if(dis[v]>dis[u]+Len[i]){
                    dis[v]=dis[u]+Len[i];
                    ind[v]=1; 
                    if(!vis[v]) q.push(pii(-dis[v],v)),vis[v]=1;
                }
            }
        }
    }
    int main()
    {
        int M,K,u,v,w,ans=0;
        scanf("%d%d%d",&N,&M,&K);
        rep(i,1,M){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }
        rep(i,1,K){
            scanf("%d%d",&a[i],&b[i]);
            add(1,a[i],b[i]);
        }
        SPFA();
        rep(i,1,K){
            if(dis[a[i]]<b[i]) ans++;
            else if(dis[a[i]]==b[i]&&ind[a[i]]>1){
                ans++; ind[a[i]]--;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

    C .Jzzhu and Apples

    pro:给定N,表示有数字1到N,如果不互质的两个数可以配对,现在问最多可以配对多少对。

    sol:(我好菜啊,不会构造,没看题解不会做系列)。从小到大枚举大于2的素数p,把没有配对的 p的倍数抽出来,如果有num个,当num为偶数时,两两配对即可; 否则,其中一个不嫩配对,那么我们把2*p拿出来即可。 即是,这写被单出来的数字都有因子2,最后他们之间又可以配对。 这样可以保证最大化配对。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    int vis[maxn],a[maxn],b[maxn],tot;
    int p[maxn],cnt,N,q[maxn],num;
    void getprime()
    {
        for(int i=2;i<=N;i++){
            if(!vis[i]) p[++cnt]=i;
            for(int j=1;j<=cnt&&i*p[j]<=N;j++){
                vis[i*p[j]]=1;
                if(!(i%p[j])) break;
            }
        }
    }
    int main()
    {
        scanf("%d",&N);
        if(N==1||N==2) return puts("0"),0;
        getprime();
        rep(i,1,N) vis[i]=0;
        vis[1]=1;
        rep(i,2,cnt){
            num=0; int pos=1;
            for(int j=p[i];j<=N;j+=p[i])
              if(!vis[j]) q[++num]=j;
            if(num&1) swap(q[1],q[2]),pos=2;
            rep(j,pos,num){
                tot++; a[tot]=q[j]; b[tot]=q[++j];
                vis[a[tot]]=vis[b[tot]]=1;
            }
        }
        num=0; int pos=1;
        for(int j=p[1];j<=N;j+=p[1])
           if(!vis[j]) q[++num]=j;
        if(num&1) swap(q[1],q[2]),pos=2;
        rep(j,pos,num){
            tot++; a[tot]=q[j]; b[tot]=q[++j];
            vis[a[tot]]=vis[b[tot]]=1;
        }
        printf("%d
    ",tot);
        rep(i,1,tot) printf("%d %d
    ",a[i],b[i]);
        return 0;
    }

    D . Jzzhu and Numbers

    pro:给定大小为N的数组a[],问多少个非空子集的&=0;答案%1e9+7;

    sol:容斥,用全集减去有公共部分的地方,如果x中有g(x)个1,而有f(x)个y满足 y&x=x;那么其贡献是(-1)^g(x)*(2^f(x)-1);而后者可以用高维前缀和求超集。

    注意!(j&(1<<i))的时候括号不要少了,这里失误几次了。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=4000010;
    const int Mod=1e9+7;
    int t[maxn],num[maxn],pw[maxn],ans;
    int main()
    {
        int N,M=1000000,x; scanf("%d",&N); pw[0]=1;
        rep(i,1,M) t[i]=t[i>>1]+(i&1),pw[i]=pw[i-1]*2%Mod;
        rep(i,1,N) scanf("%d",&x),num[x]++;
        rep(i,0,20)
         rep(j,0,M) {
             if(!(j&(1<<i))) (num[j]+=num[j|(1<<i)])%=Mod;
        }
        rep(i,0,M){
            if(t[i]&1) ans=(ans-(pw[num[i]]-1)+Mod)%Mod;
            else ans=(ans+(pw[num[i]]-1))%Mod;
        }
        printf("%d
    ",ans);
        return 0;
    }

    E .Jzzhu and Squares

    高斯消元+矩阵  不会,占位

  • 相关阅读:
    C#.NET常见问题(FAQ)-浮点数如何四舍五入
    C#.NET常见问题(FAQ)-方法参数带ref是什么意思
    C#.NET常见问题(FAQ)-list比数组效率低多少
    C#.NET常见问题(FAQ)-如何输出带选项的MessageBox,YESNO
    微软企业库Unity学习笔记
    微软企业库5.0---缓存模块
    学习微软企业库--日志模块
    学习微软企业库存心得--总结
    C#获取网页内容,并且处理正确编码
    C#获取网页内容的三种方式
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10459098.html
Copyright © 2020-2023  润新知