Codeforces Round 257 (Div. 2)

传送门

A - Jzzhu and Children (签到)

题意

模拟给N个孩子发糖一次发M个 每个孩子需要a[i]个糖 如果给的糖满足孩子的需要孩子就会走,不满足就会到队伍最后 问你最后走的孩子编号

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    queue<pair<int,int> >pq;
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int a;
        cin>>a;
        pq.push({a,i});
    }
    int last=-1;
    while(!pq.empty()){
        int aa=pq.front().first;
        last=pq.front().second;
        pq.pop();
        aa-=m;
        if(aa>0)pq.push({aa,last});
    }
    cout<<last;
    return 0;
}

B - Jzzhu and Sequences ( 矩阵快速幂)

题意

a[1]=x,a[2]=y,a[i]=a[i+1]+a[i-1]

让你求a[n]

思路

可以发现a[i]=a[i-1]-a[i-2];

然后就可以矩阵快速幂了,或者可以多推几项发现这个数论是6个一循环

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
typedef vector<ll>vec;
typedef vector<vec>mat;
mat mul(mat& A,mat &B){
    mat C(A.size(),vec(B[0].size()));
    for(int i=0;i<A.size();i++)
        for(int k=0;k<B.size();k++)
        if(A[i][k])
            for(int j=0;j<B[0].size();j++)
            C[i][j]=(C[i][j]+A[i][k]*B[k][j]%mod+mod)%mod;
    return C;
}
mat Pow(mat A,ll n){
    mat B(A.size(),vec(A.size()));
    for(int i=0;i<A.size();i++)B[i][i]=1;
    for(;n;n>>=1,A=mul(A,A))
        if(n&1)B=mul(B,A);
    return B;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    ll x,y,n;
    cin>>x>>y>>n;
    x=(x+mod)%mod;y=(y+mod)%mod;
    if(n==1)cout<<x,exit(0);
    if(n==2)cout<<y,exit(0);
    mat a=mat(2,vec(2));
    a[0][0]=1;a[0][1]=-1;
    a[1][0]=1;a[1][1]=0;
    a=Pow(a,n-2);
    mat b=mat(2,vec(1));
    b[0][0]=y;
    b[1][0]=x;
    a=mul(a,b);
    cout<<(a[0][0]+mod)%mod<<endl;
    return 0;
}

C - Jzzhu and Chocolate (思维)

题意

给你一个矩形巧克力

你可以横切竖切,但是只能在巧克力的内边并且不能破坏巧克力的内部

让你切K刀 使得最小面积最大

思路

可以发现如果K>n+m-2是不能完全切完

然后贪心的做法就是这K刀全部切同一个方向,然后不足K到的切其他方向

为什么可以全部切同一方向呢,假设我们现在有一个4×6的巧克力 我们现在在切一竖刀 变成2×6=12的巧克力 如果我们切横刀变成4乘3=12的巧克力,那么如果我们两刀都切横

1×6=6 如果两刀交叉切 变成2乘3=6的巧克力

如果两道都竖切,变成4乘2=8的巧克力 明显答案更优

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    ll n,m,k;

    cin>>n>>m>>k;
    ll cancut=n+m-2;
    ll ans=0;
    if(k>cancut)cout<<-1,exit(0);
    else{
        if(k>=n)ans=max(ans,1LL*m/(k-n+2LL));
        if(k>=m)ans=max(ans,1LL*n/(k-m+2LL));
        if(k<n)ans=max(ans,1LL*m*(n/(k+1LL)));
        if(k<m)ans=max(ans,1LL*n*(m/(k+1LL)));
    }
    cout<<ans<<endl;
    return 0;
}

D - Jzzhu and Cities (最短路)

题意

给你一个无向图,结点1为首都

有m条铁路 每条铁路有距离 同时有K条直通首都的航线 同时也有距离

现在想要关掉最多航线,同时使得首都到其他点的最短路不变

思路

一开始以为是求个最小生成树....

后来发现直接求个最短路 然后航线也参与最短路的求解中,有其他的路线更新了这个航线的距离就可以把这个航线给去掉了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m,k;
vector<pii>G[maxn];
ll d[maxn];
int vis[maxn];
int need[maxn];

int dij(){
    fill(d,d+maxn,1e18);
    d[1]=0;
    queue<int>pq;
    vis[1]=1;
    pq.push(1);
    for(int i=1;i<=k;i++){
        int u,x;
        cin>>u>>x;
        if(d[u]>x){
            d[u]=x;need[u]=1;
            if(vis[u]==0){
                pq.push(u);
                vis[u]=1;
            }
        }
    }
    while(!pq.empty()){
        int u=pq.front();pq.pop();
        vis[u]=0;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i].first,x=G[u][i].second;
            if(d[v]>=d[u]+x&&need[v])need[v]=0;
            if(d[v]>d[u]+x){
                d[v]=d[u]+x;
                if(vis[v]==0){
                    vis[v]=1;
                    pq.push(v);
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        k-=need[i];
    }
    return k;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int u,v,x;
        cin>>u>>v>>x;
        G[u].push_back({v,x});
        G[v].push_back({u,x});
    }
    cout<<dij()<<endl;
    return 0;
}

E - Jzzhu and Apples (大模拟+素数)

题意

给N个苹果编号1-n 然后两两分组,并且同一组的两个苹果的编号不能互质

让你求出最大分组数和分组情况

思路

首先偶数肯定是可以分组的

然后我们就考虑奇数

发现奇数 能匹配是需要有倍数关系的,然后我们就枚举每个奇数 发现复杂度有点爆炸 其实我们可以直接枚举素数,然后把素数和他的倍数放在一起,如果是偶数个那就直接分组了

如果是奇数个,那就最好把其中一个偶数拿出来 其他的分组,这样处理

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int vis[maxn];

int prime[maxn];
bool check[maxn];
int tot;

void init(int n){
    tot=0;
    for(int i=2;i<=n;i++){
        if(!check[i]){
            prime[++tot]=i;
        }
        for(int j=1;j<=tot;j++){
            if(i*prime[j]>n)break;
            check[i*prime[j]]=true;
            if(i%prime[j]==0)break;
        }
    }
}

vector<int>L,R;


int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n;
    cin>>n;
    init(n);
    for(int i=2;i<=tot;i++){
        vector<int>s;
        int x=prime[i];
        for(int j=x;j<=n;j+=x)
            if(!vis[j])s.push_back(j);
        int cnt=s.size();
        if(cnt&1){
            for(int j=0;j<cnt;j++){
                if(s[j]%2==0){
                    s.erase(s.begin()+j);break;
                }
            }
        }
        cnt=s.size();
        for(int j=1;j<cnt;j+=2){
            vis[s[j-1]]=1;vis[s[j]]=1;
            L.push_back(s[j-1]);R.push_back(s[j]);
        }
    }
    vector<int>even;
    for(int i=2;i<=n;i+=2)if(!vis[i])even.push_back(i);
    int cnt=even.size();
    for(int i=1;i<cnt;i+=2)L.push_back(even[i-1]),R.push_back(even[i]);
    cout<<L.size()<<endl;
    for(int i=0;i<L.size();i++)
        cout<<L[i]<<" "<<R[i]<<endl;
    return 0;
}
posted @ 2019-03-04 15:04  luowentao  阅读(200)  评论(0编辑  收藏  举报