您的位置:首页 > 编程语言 > C语言/C++

C++——NOIP模拟题——零件加工

2017-04-22 15:03 190 查看


零件加工


题目描述

工匠小 K 最近有 n 个零件需要加工。每个零件都需要 ti 天的时间来完成,每个零件每延迟一天加工都要缴纳一定的罚金 si 。延迟的天数为从今天算起到该工作开始的那天,第一个零件加工没有罚金。现在小 K 想知道怎样安排加工顺序可以使他要交的罚金最少,最少是多少?

这个数可能会很大,请输出这个数对 m 取模后的结果。


输入格式

输入文件第一行为一个整数 n ,表示需要加工的零件总数。

第二行为一个整数 m ,表示答案要对 m 取模。

第 3~n+2 行,每行两个整数 ti 和 si。


输出格式

输出仅一行,一个整数,表示小 K 最少要缴纳的罚金对 m 取模的结果。


样例数据 1

输入



100 

2 33 

33 2
输出

4


样例数据 2

输入



100 

3 3 

6 4 

2 2 

8 5
输出

81


备注

【样例1解释 】

先加工第一个,需要 2 天时间,再加工第二个。需要缴纳的罚金为 2×2=4 。
【样例2解释】

如果按照 1→2→3→4 的顺序进行加工,需要缴纳的罚金为:

     0×3+3×4+(3+6)×2+(3+6+2)×5=85 

最佳方案是 3→1→2→4,此时需要缴纳的罚金为:

     0×2+2×3+(2+3)×4+(2+3+6)×5=81
【数据范围】

对于 40% 的数据,0<n≤10,000;0<ti,si≤10,000; 

对于 80% 的数据,0<n≤100,000;0<ti,si≤2×109,0<m≤108; 

对于 100% 的数据,0<n≤100,000;0<ti,si≤2×109,0<m≤1018。

解题报告:

关键词:贪心

按照t/s升序排序然后计算,比较大小的时候注意交叉相乘。

对于最后20%的数据相乘时可以使用二进制乘法以避免高精度:
long long mul(long long a,long b)
{
long long ret=0;
while(a)
{
if(a&1)ret=(ret+b)%MOD;
a>>=1;
b=(b<<1)%MOD;
}
return ret;
}

时间复杂度:O(nlog2n) 
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
struct node{
long long t,s;
}a[100001];
long long m;
inline long long readint()
{
long long i=0,f=1;
char ch;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
for(;ch>='0' && ch<='9';ch=getchar())
i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}
inline bool cmp(const node &a,const node &b)
{
return a.t*b.s<a.s*b.t;
}
inline long long mu(long long a,long long b)
{
long long r;
for(r=0;b;a=(a<<1)%m,b>>=1)
if(b&1) r=(r+a)%m;
return r;
}
int main()
{
static long long n,i,ans,sum;
n=readint();
m=readint();
for(i=1;i<=n;++i) a[i].t=readint(),a[i].s=readint();
std::sort(a+1,a+1+n,cmp);
for(i=2;i<=n;++i)
{
sum=(sum+a[i-1].t)%m;
ans=(ans+mu(sum,(a[i].s%m)))%m;
}
printf("%I64d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言