外星生成器C\C++
20210822修改
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据占一行,包含一个整数 G。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为 Case #x: y,其中 x 为组别编号(从 1 开始),y 为满足条件的 K 的数量。
数据范围
全部数据:1≤T≤100。
测试点 1(小数据测试点):1≤G≤104。
测试点 2(大数据测试点):最多不超过 20 组数据满足,1≤G≤1012,其余数据满足,1≤G≤104。
输入样例:
2
10
125
输出样例:
Case #1: 2
Case #2: 4
问题拿到手有点懵,想一想觉得是数学问题。开始还想用前缀和做的,一看大数据点1≤G≤10^12......后来再看后一天会比前一天多生产一个金条,就是第n+1天比第n天多一个,但一共最多只能生产G个金条,所以想办法生产最多就是G个嘛虽然题目也明确说了
突然发现一个规律 所有奇数至少可以拆成2种:它本身是一种和(x-1)/2,(x-1)/2+1是一种,而(x-1)/2+(x-1)/2+1=x就是符合机器生产的规律 这个规律也可以这么表示 (x-1)%2==0
往后到分成3个数,比如6=1+2+3,可以看成1+(1+1)+(1+2)=1x3+3;
到分成4个数,比如10=1+2+3+4,可以看成1+(1+1)+(1+2)+(1+3)=1x4+6;
其实这个问题的本质就是公差为一的等差数列,每增一天项数加一,生产金条比前一天多一
问题到这里其实已经解决了。不难看出有个通式(设上述的1为X)
G=nX+(1+n-1)(n-1)/2
化成编成人喜欢看的就是
(G-(n-1)n/2)%n==0
n的计算就交给计算机咯
代码来了~~
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int T;
long long g, k, s;
int main(){
scanf("%d", &T); \\多组样例
for(int j=1; j<=T; j++){
s=k=0;
cin>>g;
for(int i=1; ;i++){
s+=i;
if(g==s||g-s<0) break; \\不管g是等于当前s还是比它小都跳出,最后加上它自己让k+1就行了
if((g-s)%(i+1)==0) k++;
}
printf("Case #%lld: %lld\n", j, ++k); \\别忘了按要求输出
}
return 0;
}
非常简陋,请大佬们多多指点( ̄︶ ̄)