codeforces数学1600day4[贪心数学公式推导CodeForces - 1151D ,思维CodeForces - 1085C,数论同余+组合计数 CodeForces - 1056B]

A - Stas and the Queue at the Buffet CodeForces - 1151D


题目大意:就是给你n个人在排队,每个人都有一个ai值和bi值,每个人的不满意度就是 f ( i ) = a i ∗ ( p o s − 1 ) + b i ∗ ( n − p o s ) f(i) = ai * (pos - 1) + bi * (n - pos) f(i)=ai(pos1)+bi(npos)pos就是每个人在的位置ps:[队伍是从左到右来排的]
现在要求的就是最小化下面
∑ i = 1 n f ( i ) \sum_{i=1}^{n}f(i) i=1nf(i)


解题思路:
对于任意的ai,aj(假设i在j的后面)对于这两个人的不满意度之和就是
s u m 1 = a i ∗ ( p o s − 1 ) + b i ∗ ( n − p o s ) + a j ∗ p o s + b j ∗ ( n − p o s − 1 ) sum1 = ai * (pos - 1) + bi * (n - pos) + aj * pos + bj * (n - pos - 1) sum1=ai(pos1)+bi(npos)+ajpos+bj(npos1)
假如把它们把两个人换过来
s u m 2 = a j ∗ ( p o s − 1 ) + b j ∗ ( n − p o s ) + a i ∗ p o s + b i ∗ ( n − p o s − 1 ) sum2 = aj * (pos - 1) + bj * (n - pos) + ai * pos + bi * (n - pos - 1) sum2=aj(pos1)+bj(npos)+aipos+bi(npos1)
假如说换过来最优那么sum2 - sum1<0整理得(pos可消掉)
a i − b i − a j + b j < 0 ∣ ∣ 反 过 来 ai - bi - aj + bj < 0||反过来 aibiaj+bj<0

/*
最k大值最小 ---> 二分答案

*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,LL> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
PII a[N];

bool cmp(PII a, PII b)
{
    return a.s - a.f + b.f - b.s < 0;
}

int main()
{
    int n = read();
    _for(i,1,n+1) 
    {
        LL l = read(), r = read();
        a[i] = {l,r};
    }
    sort(a+1,a+n+1,cmp);
    LL res = 0;
    _for(i,1,n+1)
        res += a[i].f * (i - 1) + a[i].s * (n - i);
    cout << res << endl;
    return 0;
}

B - Connect Three CodeForces - 1085C


首先两点间连起来最少需要的格子为他们的曼哈顿距离
将三个点以纵坐标排序,记录横坐标最大最小值。中间的点向左右两点的横向扩展,旁边两点纵向向中间点扩展。


/*
最k大值最小 ---> 二分答案

*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,LL> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
set <pair<int, int> >st;
struct node
{
    int x, y;
}a[105];
bool cmp(struct node a, struct node b)
{
    return a.x > b.x;
}
int main()
{
    int i, j, k, n, m;
    for(i = 0; i < 3; i++)cin >> a[i].x >> a[i].y;
    sort(a, a + 3, cmp);
    int l1, l2, r1, r2;
    l1 = max(max(a[0].y, a[1].y), a[2].y);
    l2 = min(min(a[0].y, a[1].y), a[2].y);
    r1 = max(max(a[0].x, a[1].x), a[2].x);
    r2 = min(min(a[0].x, a[1].x), a[2].x);
    //for(i = 0; i < 3; i++)cout << a[i].x << " " << a[i].y << endl;
    for(i = l2; i <= l1; i++)
    {
        //if(i == a[1].y)continue;
        //cout << a[1].x << " " << i << endl;
        st.insert(make_pair(a[1].x, i));
    }
    //cout << l1 << " " << l2 << " " << r1 << " " << r2 << endl;
    for(i = r2; i <= a[1].x; i++)
    {
        //if(i == a[0].x)continue;
        st.insert(make_pair(i, a[2].y));
    }
    for(i = a[1].x; i <= r1; i++)
    {
        //if(i == a[2].x)continue;
        st.insert(make_pair(i, a[0].y));
    }
    cout << st.size() << endl;
    set<pair<int, int> >::iterator it;
    for(it = st.begin(); it != st.end(); it++)
    {
        cout << it -> first << " " << it -> second << endl;
    }
    return 0;
}


C - Divide Candies CodeForces - 1056B


题目大意:就是给你一个 n ∗ n n*n nn得矩阵每个位置坐标从1到n。现在给你一个数m。问有多少个坐标 ( i , j ) (i,j) (i,j)满足 ( i 2 + j 2 ) % m = = 0 (i^2 + j^2)\%m==0 (i2+j2)%m==0
求:
∑ i = 1 n ∑ j = 1 n [ ( i 2 + j 2 ) % m = = 0 ] \sum_{i=1}^{n}\sum_{j=1}^n[(i^2+j^2)\%m==0] i=1nj=1n[(i2+j2)%m==0]
n ∈ [ 1 , 1 e 9 ] , m ∈ [ 1 , 1000 ] ; n\in[1,1e9],m\in[1,1000]; n[1,1e9],m[1,1000];


解题思路:1.因为n非常大从n入手显然很不现实。我们应该从m入手。
2. ( i 2 + j 2 ) % m = = 0 (i^2+j^2)\%m==0 (i2+j2)%m==0根据同余方程式这个也可以写成 ( i 2 % m + j 2 % m ) % m = = 0 (i^2\%m+j^2\%m)\%m==0 (i2%m+j2%m)%m==0因为 % m \%m %m之后数值大小就会 ∈ [ 0 , m − 1 ] \in[0,m-1] [0,m1]那么 ( i 2 % m + j 2 % m ) = = m (i^2\%m+j^2\%m)==m (i2%m+j2%m)==m
3.因为 i j i\quad j ij都是独立取值我们可以分开考虑
4.对于 i 2 % m = = ( i % m ) ∗ ( i % m ) % m i^2\%m==(i\%m)*(i\%m)\%m i2%m==(i%m)(i%m)%m对于单个 i % m i\%m i%m是有循环节的那么 ( i 2 % m ) (i^2\%m) (i2%m)也是有循环节的对于每个循环节我们统计一下每个余数出现的次数就可以了具体看代码


/*
最k大值最小 ---> 二分答案

*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,LL> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
LL mod[N];
bool vis[N];
int main()
{
    LL n, m, res = 0;
    cin >> n >> m;
    if(n <= 3000)
    {
        _for(i,1,n+1)
         _for(j,1,n+1)
          if((i * i + j * j) % m == 0) res ++;
             cout << res << endl;
             return 0;
    }
    
    _for(i,1,m+1)
      mod[(i * i) % m] ++;
      
    _for(i,1,m+1)
        if(!vis[(i * i) % m])
        {
            mod[(i * i) % m] *= n / m;
            vis[(i * i) % m] = true;
        }
     
    _for(i,1,n % m+1)
     mod[(i * i) % m] ++;
    
    _for(i,0,m+1)
      if(i == 0) res += mod[0] * mod[0];
      else   res += mod[i] * mod[m - i];
    
    cout << res << endl;
    return 0;
}

你可能感兴趣的:(codeforces数学1600day4[贪心数学公式推导CodeForces - 1151D ,思维CodeForces - 1085C,数论同余+组合计数 CodeForces - 1056B])