对于这种题,首先一开始就要对给出的公式进行研究,从这里入手是正道。
分析公式 3n(n−1)+1 ,若给出一个数n,假设要k个3n(n−1)+1加起来得到n,即 3n(n-1)k+k=n,注意到3n(n-1)k是6的倍数,那么求的是满足(n-k)%6==0的最小的k。还有就是要注意到1、2要特判,即k要从3开始枚举
打表发现规律了就好做了、 当n%6==1 时要考虑能否由1个数组成在表中找到就可以 否则就需要7项的和了(规律跑个程序或者列举一些数就发现了)
当n%6==2时 要考虑能否由2个数组成 根据表中数据列举一些数(跑个程序更快更简洁)会发现只有2和8两种情况
剩下的就注意一下是6的倍数的直接输出6否则输出n%6即可
/*附上渣渣程序
#include<stdio.h>
int main()
{
int i, j;
for(i = 7; i <= 100; i++)
{
for(j = 1; j < 10; j++)
{
if((i-j) % 6 == 0 && i != j && i%6==1)
printf("%d %d\n", i, j);
}
}
for(i = 7; i <= 100; i++)
{
for(j = 1; j < 10; j++)
{
if((i-j) % 6 == 0 && i != j && i%6==2)
printf("%d %d\n", i, j);
}
}
return 0;
}
*/
#include<cstdio> #include<cstring> #include<stack> #include<vector> #include<queue> #include<cmath> #include<cstdlib> #include<algorithm> using namespace std; const int oo = 0x3f3f3f3f; const int maxn = 1e6+7; const int mod = 1e9+7; int Soda[maxn]={1}, id;///id为最后一个数的下标 void init()///打表 { for(int i=1; i<=20000; i++) { Soda[i]=3*i*(i-1)+1; if(Soda[i] >= mod-7) {id = i; break;} } } int Search(int left, int right, int x)///二分查找 { int mid = (left+right)/2; if(Soda[mid] == x) return 1; if(left > right) return 0; if(Soda[mid] < x) return Search(mid+1, right, x); else return Search(left, mid-1, x); } int main() { init();///打表 int T, i, n, ans; // for(i = 0; i < 20; i++) // printf("%d\n", Soda[i]); scanf("%d", &T); while(T--) { scanf("%d", &n); if(n%6==1) { if(Search(0, id, n)) ans = 1; else ans = 7; } else if(n%6==2) { int ok = 0, p = id; for(i = 1; i <= p; i++) { while(Soda[i] + Soda[p] > n) p--; if(Soda[i]+Soda[p] == n) { ok = 1; break; } } if(ok) ans = 2; else ans = 8; } else { ans = n%6; if(ans == 0) ans = 6; // ans = (n-1)%6+1; } printf("%d\n", ans); } return 0; }
来源:https://www.cnblogs.com/PersistFaith/p/4962494.html