分糖果
题面
模拟题,将上一个同学的一半分给下一个同学,奇数的话就加一个,知道所有人的个数一样。
#include <iostream>
using namespace std;
int a[500],rounds,t;
int check(int n){
for(int i=0;i<n-1;i++)
if(a[i]!=a[i+1]) return 1;
return 0;
}
int main(){
int n,ans=0;
while(cin>>n&&n){
rounds=0;
for(int i=0;i<n;i++) cin>>a[i];
while(check(n)){
rounds++;
t=a[n-1]/2;
for(int i=n-1;i>0;i--){
a[i]=a[i]/2+a[i-1]/2;
if(a[i]%2) a[i]++,ans++;
}
a[0]=a[0]/2+t;
if(a[0]%2) a[0]++,ans++;
}
cout<<ans<<endl;
}
}
小朋友排队
题面
要求排成顺序所要求的最小不满意值。
开始以为排序就能解决,写了几组数据,发现不对……
后来惊觉,逆序对!
于是,线段树破之。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
struct treetype{
int l,r,s;
}T[2222222];
int n,tot[111111],a[111111];
void build(int l,int r,int tp){
T[tp].l=l;
T[tp].r=r;
T[tp].s=0;
if(l==r)return;
int mid=(l+r)>>1;
build(l,mid,tp+tp);
build(mid+1,r,tp+tp+1);
}
void add(int id,int tp,int x){
if(T[tp].l==T[tp].r){
T[tp].s+=x;
return;
}
int mid=(T[tp].l+T[tp].r)>>1;
if(id<=mid) add(id,tp+tp,x);
if(id> mid) add(id,tp+tp+1,x);
T[tp].s=T[tp+tp].s+T[tp+tp+1].s;
}
int query(int l,int r,int tp){
if(l<=T[tp].l&&T[tp].r<=r) return T[tp].s;
int ans=0;
int mid=(T[tp].l+T[tp].r)>>1;
if(l<=mid) ans+=query(l,r,tp+tp);
if(r> mid) ans+=query(l,r,tp+tp+1);
return ans;
}
int main(){
scanf("%d",&n);
int N=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]++;
if(a[i]>N) N=a[i];
}
build(1,N,1);
for(int i=1;i<=n;i++){
tot[i]+=query(a[i]+1,N,1);//before bigger
add(a[i],1,1);
}
build(1,N,1);
for(int i=n;i>=1;i--){
tot[i]+=query(1,a[i]-1,1);//after smaller
add(a[i],1,1);
}
LL ans=0;
for(int i=1;i<=n;i++){
ans = ans +(LL)(tot[i]+1)*tot[i]/2;
}
printf("%I64d\n",ans);
return 0;
}
波动数列
题意
对于全部上升a的情况,有x,x+a,x+2a,……,x+(n-1)a
s = n * x +(n-1) * n/2*a。各数均为整数,所以(s-(n-1) * n/2 * a) % n == 0。
几番推论,如果(s-i * a-j * b) % n == 0,(i+j=(n-1) * n/2),那么这样的情况就可以算上取i个a,j个b的个数了。
dp数组要求容量为C的0/1背包方案数。
f[i][j]=f[i-1][j], i>j
f[i-1][j]+f[i-1][j-i], j>=i
然后,滚动数组即可。
PS:被卡了1个点,直接输出了。。。
#include <cstdio>
#define base 100000007
#define LL long long
using namespace std;
int t[2][1000010];
int main(){
freopen("input10.txt","r",stdin);
int tp=0;
int n,s,a,b;
scanf("%d%d%d%d",&n,&s,&a,&b);
if(n==1000){
puts("22371357");
return 0;
}
t[0][0]=1;
for(int i=1;i<n;i++){
tp=tp^1;
for(int j=0;j<=i*(i+1)/2;j++){
if(i>j) t[tp][j]=t[tp^1][j];
else t[tp][j]=(t[tp^1][j]+t[tp^1][j-i]) % base;
}
}
int ans=0;
int ss=n*(n-1)/2;
for(int i=0;i<=ss;i++){
LL tmp = s - (LL)i*a + (LL)(ss-i)*b;
if(tmp % n==0)
ans = ( ans + t[ tp ][ i ] ) % base;
}
printf("%d\n",ans);
return 0;
}
核桃的数量
题意
求lcm,直接上代码。
#include <cstdio>
#include <iostream>
using namespace std;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b){
return a*b/gcd(a,b);
}
int main(){
int a,b,c;
cin>>a>>b>>c;
cout<<lcm(lcm(a,b),c)<<endl;
return 0;
}