ZOJ 补题 3903 && 3905 && 3911 (ZOJ Monthly, October 2015)

ZOJ 3903 Ants

【题目链接】:click here~~

【题目大意】给出一个长方体的最长边的长度,求在所有可能的情况下,在表面上从一个对角线到另一个对角线经过路径的平方和

【思路】:

只给出一个最长边,可以枚举其他两边,例如最长边假如给出3,那么 所有的可能长方体为

{1,1,3},{1,2,3},{1,3,3},{2,2,3},{2,3,3},{3,3,3},n>3的情况下打表发现

打表代码:

for(int i=1; i<=n; ++i)
            for(int j=i; j<=n; ++i)
            {
                 int k=i+j;
                 s+=(n*n+k*k);
            }

其实就是所有组合的可能,最后加上n*(n+1)/2个n^2

那么答案就来了,对于题目数据范围n<=10^14,还有一个取模,自然想到要乘以逆元,不然WA,当然java大数直接可以秒(博主java写挫了,RE中,最后换成C++,快速幂一遍)

C++代码:

/*
* Problem: ZOJ No.3903
* Running time: 0MS
* Complier: G++
* Author: herongwei
* Create Time: 16:50 2015/10/11 星期日
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
typedef long long LL;
const LL mod = (LL)(1e9)+7;
LL n;
LL poww(LL a, LL b)
{
    LL res=a, ans=1;
    while(b){
        if(b&1) ans=res*ans%mod;
        b>>=1;
        res=res*res%mod;
    }
    return ans;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%lld",&n);n%=mod;
        LL s1 = (1+n)%mod*n%mod*poww(2, mod-2)%mod;
        LL s2 = (1+n)%mod*(2*n+1)%mod*n%mod*poww(6, mod-2)%mod;
        LL ans = (poww(n,4)+2*n%mod*s2%mod+2*s1%mod*s1%mod)%mod;
        LL ans1 =(4*s2%mod + poww(n,3))%mod;
        ans=(((ans-ans1)%mod+mod)%mod*poww(2, mod-2)%mod+ ans1)%mod;
        printf("%lld\n", ans);
    }
    return 0;
}

ZOJ 3905 Cakes

【题目链接】:click here~~

【题目大意】给你n个蛋糕,每个分别有两个属性ai,bi,每次让Bob选择两个蛋糕bi属性最大的,那么Alice就选剩下的ai最大的,问如何安排选的顺序使得Alice选的价值最大

【思路】把bi从大到小排序一下,问题转化一下,从n个数中选取m(此题m=(1+n)/2)个物品价值最大的方案,就是一个dp了。

代码:

/*
* Problem: ZOJ No.3905
* Running time: 10MS
* Complier: G++
* Author: herongwei
* Create Time: 16:50 2015/10/11 星期日
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = (LL)(1e9)+7;
const int maxm=1e6+10;
const int maxn=810;
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
struct node
{
    int ai,bi;
    bool operator <(const node &t) const{
        return bi>t.bi;
    }
}st[maxm];
int dp[maxn][maxn];
int main()
{
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d", &t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; ++i)scanf("%d%d",&st[i].ai,&st[i].bi);
        sort(st,st+n);//按bi从大到小排序,保证Alice有合法选
        memset(dp,0,sizeof(dp));
        for(int i=1; i<n; ++i)//第一个蛋糕Alice一定选不到,所以从1枚举
            for(int j=1; j<=(i+1)/2; ++j)
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+st[i].ai);//当前dp[i][j]从上一个状态递推,选与不选,选的话加上ai的价值
        printf("%d\n",dp[n-1][n/2]);
    }
    return 0;
}

ZOJ 3911 Prime Query

【题目链接】:click here~~

【题目大意】:

You are given a simple task. Given a sequence A[i] with N numbers. You have to perform Q operations on the given sequence.

Here are the operations:

  • A v l, add the value v to element with indexl.(1<=V<=1000)
  • R a l r, replace all the elements of sequence with indexi(l<=i<=r) with a(1<=a<=10^6) .
  • Q l r, print the number of elements with index i(l<=i<=r) andA[i] is a prime number

Note that no number in sequence ever will exceed 10^7. 

给你一个序列,三种操作

A:a[l]的值增加v;

R:将区间【l,r】a[l]-a[r]的值替换为a

Q:输出【l,r】的素数个数

【思路】:线段树的运用

代码:

/*
* Problem: ZOJ No.3911
* Running time: 460MS
* Complier: G++
* Author: herongwei
* Create Time: 16:50 2015/10/11 星期日
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = (LL)(1e9)+7;
const int maxn=1e5+10;
const int maxm=1e7+10;
#define mid ((l+r)>>1)
#define lson (rt<<1),l,mid
#define rson (rt<<1|1),mid+1,r
bool prime[maxm];
int arr[maxn<<2];//存储数据
int prime_sum[maxn<<2];//表示素数的个数
int lazy[maxn<<2];//延迟标记
void init()
{
    memset(prime,0,sizeof(prime));
    prime[0]=prime[1]=1;
    for(int i=2; i<=10000001; ++i) if(!prime[i])
        {
            for(int j=i*2; j<=10000001; j+=i) prime[j]=1;
        }
}
void push_up(int rt)//向上更新
{
    prime_sum[rt]=prime_sum[rt<<1]+prime_sum[rt<<1|1];
}
void push_down(int rt,int l,int r)//向下更新
{
    if(lazy[rt]>0)
    {
        lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
        arr[rt]=arr[rt<<1]=arr[rt<<1|1]=lazy[rt];
        if(!prime[lazy[rt]])
        {
            prime_sum[rt<<1]=(mid-l+1);
            prime_sum[rt<<1|1]=r-mid;
        }
        else
        {
            prime_sum[rt<<1]=prime_sum[rt<<1|1]=0;
        }
        lazy[rt]=0;
    }
}
void build(int rt,int l,int r)//建树
{
    lazy[rt]=0;
    prime_sum[rt]=0;
    arr[rt]=0;
    if(l==r){
        scanf("%d",&arr[rt]);
        if(!prime[arr[rt]])prime_sum[rt]=1;
        else prime_sum[rt]=0;
        return ;
    }
    build(lson);
    build(rson);
    push_up(rt);
}
void Add(int rt,int l,int r,int pos,int val)//单点增减
{
    if(l==r){
        arr[rt]+=val;
        if(prime[arr[rt]])prime_sum[rt]=0;
        else prime_sum[rt]=1;
        return ;
    }
    push_down(rt,l,r);
    if(pos<=mid)Add(lson,pos,val);
    else Add(rson,pos,val);
    push_up(rt);
}
void Reply(int rt,int l,int r,int x,int y,int val)//区间替换
{
    if(l==x&&y==r){
        lazy[rt]=val;
        arr[rt]=val;
        if(!prime[val])prime_sum[rt]=(r-l+1);
        else prime_sum[rt]=0;
        return ;
    }
    push_down(rt,l,r);
    if(y<=mid){
        Reply(lson,x,y,val);
    }
    else if(x>mid){
        Reply(rson,x,y,val);
    }
    else{
        Reply(lson,x,mid,val);
        Reply(rson,mid+1,y,val);
    }
    push_up(rt);
}
int query(int rt,int l,int r,int x,int y)//查询
{
    if(l==x&&y==r){
        return prime_sum[rt];
    }
    push_down(rt,l,r);
    if(y<=mid){
        return query(lson,x,y);
    }
    else if(x>mid){
        return query(rson,x,y);
    }
    else{
        return query(lson,x,mid)+query(rson,mid+1,y);
    }
}
int main()
{
    init();
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d", &t);
    while(t--){
        int n,q;
        scanf("%d%d",&n,&q);
        build(1,1,n);
        while(q--){
            char op[3];
            int val,pos,l,r;
            scanf("%s",op);
            if(op[0]=='A'){
                scanf("%d%d",&val,&pos);
                Add(1,1,n,pos,val);
            }
            else if(op[0]=='R'){
                scanf("%d%d%d",&val,&l,&r);
                Reply(1,1,n,l,r,val);
            }
            else {
                scanf("%d%d",&l,&r);
                printf("%d\n",query(1,1,n,l,r));
            }
        }
    }
    return 0;
}

待续~~




你可能感兴趣的:(ZOJ,月赛)