CCF-CSP 2016-2 工资计算 暴力求解+二分法两种方法 满分题解
题目链接:CCF-CSP 2016-2 工资计算
暴力求解思路:
- 首先计算出在各个工资范围内的税费,设置一个int数组存储,即
int v[7]={45,300,900,6500,6000,8750,9000};
例如:45=1500*0.03 - 然后根据税后所得判断实际工资的具体范围,列出具体方程,求解出实际工资
- 在计算时需要注意,求解实际工资时需要加上之前范围内的税费
- 同时,需要注意工资范围的边界,例如:实际工资为8100到手只要7735,但是7735却在5000~8000的范围内,不在8000~12500的范围内,所以我们在5000~8000的范围内需要特判,如果大于等于7735,就需要按照8000~12500的范围方程进行求解
- 一个小提示:这里的s设置为double类型,否则在70080即实际工资为100000时,最后只能得到99999的结果
- 在选择数据范围时,主要到税前工资为一个整百的数
- 该方法只是纯粹的数学方法,实现过程十分繁琐,但是思路简单易懂;
具体代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int t;
double s;//double转int时的精度有问题
int v[7]={45,300,900,6500,6000,8750,9000};//税费
int main()
{
cin>>t;
if(t<=3500)
{
s = t;
}
else if(t>3500&&t<=5000)//5045是5100的实发工资
{
int temp = t - 3500;
s = (temp+3395)/0.97;//temp+(s-3500)*0.03=s-3500
}
else if(t>5000&&t<=8000)
{
int temp =t+v[0];
if(temp>=7735)//7735是8100的实发工资
{
s = (temp-1600)*0.8;
}
else s = (temp-500)/0.9;//temp+(s-5000)*0.1=s
}
else if(t>8000&&t<=12500)
{
int n = 1;
int temp = t;
for(int i=0;i<=n;i++)
{
temp+=v[i];
}
if(temp>=11330)//11330是12600的实发工资
{
temp+=v[n+1];
s = (temp-3125)/0.75;
}
else s = (temp-1600)/0.8;//temp+(s-8000)*0.2=s
}
else if(t>12500&&t<=38500)
{
int n = 2;
int temp = t;
for(int i=0;i<=n;i++)
{
temp+=v[i];
}
if(temp>=30825)//30825是38600的实发工资
{
temp += v[n+1];
s = (temp-11550)/0.7;
}
else s = (temp-3125)/0.75;//temp+(s-12500)*0.25=s
}
else if(t>38500&&t<=58500)
{
int n = 3;
int temp = t;
for(int i=0;i<=n;i++)
{
temp+=v[i];
}
if(temp>=44820)//44820是58600的实发工资
{
temp +=v[n+1];
s = (temp-20475)/0.65;
}
else s = (temp-11550)/0.7;//temp+(s-38500)*0.3=s
}
else if(t>58500&&t<=83500)
{
int n = 4;
int temp = t;
for(int i=0;i<=n;i++)
{
temp+=v[i];
}
if(temp>=61060)//61060是83600的实发工资
{
temp +=v[n+1];
cout<<temp<<endl;
s =(temp-37575)/0.55;
}
else s = (temp-20475)/0.65;//temp+(s-58500)*0.35=s
}
else if(t>83500&&t<=100000)
{
int n = 5;
int temp = t;
for(int i=0;i<=n;i++)
{
temp+=v[i];
}
s = (temp-37575)/0.55;//temp+(s-83500)*0.45=s
}
cout<<s<<endl;
return 0;
}
注意:此方法在其他测试网站上可以AC,但是在CCF-CSP官网上却只有50分,欢迎大佬讨论!!!
二分法求解思路:
- 该方法在方法一的基础上进行了优化,不需要计算出各个工资范围之间的税费
- 直接利用二分查找,找到符合条件的实际工资
- get函数是计算税后工资
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int t;
//计算税前工资
int get(int k){
int a[] = {0, 1500, 4500, 9000, 35000, 55000, 80000, 1000000};//工资范围
double r[] = {0, 0.03, 0.1, 0.2, 0.25, 0.3, 0.35, 0.45};//税率
if(k <= 3500) return k;
int tax = k - 3500;
double sum = 0;//记录减去的税费
for(int i = 1; i <= 7; i ++)
{
if(tax >= a[i])
{
sum += (a[i] - a[i - 1]) * r[i];//加上减去的税
}
else
{
sum += (tax - a[i - 1]) * r[i];
break;
}
}
return k - sum;
}
int main()
{
cin >> t;
int l = t, r = t * 2;//设置二分范围
while (l < r)
{
int mid = (l + r) >> 1;
if(get(mid) >= t) r = mid;
else l = mid + 1;
}
cout <<l<<endl;
return 0;
}