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;
}
待续~~