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; }
【题目链接】: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; }
【题目链接】: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:
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; }