杨辉三角形
暴力能过40%,两个数组维护一层一层往下算
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
ll N;
vector<ll> t1;
vector<ll> t2;
ll cnt;
void solve()
{
if(N==1) {cnt=1;return;}
t1.push_back(1);
t1.push_back(1);
cnt = 3;
int flag = 0;
while(1)
{
// t2
t2.push_back(1);
cnt++;
for(int i=0;i<t1.size()-1;i++)
{
ll x = t1[i]+t1[i+1];
cnt++;
if(x==N) {flag=1;break;}
t2.push_back(x);
}
if(flag) break;
t2.push_back(1);
cnt++;
t1.clear();
// t1
t1.push_back(1);
cnt++;
for(int i=0;i<t2.size()-1;i++)
{
ll x = t2[i]+t2[i+1];
cnt++;
if(x==N) {flag=1;break;}
t1.push_back(x);
}
if(flag) break;
t1.push_back(1);
cnt++;
t2.clear();
}
}
int main()
{
cin >> N;
solve();
cout << cnt << endl;
return 0;
}
全部数据能过
#include<iostream>
using namespace std;
typedef long long ll;
ll N;
int n, k; // 组合数,Cnk,可以确定第几行第几个,但求是斜着
ll combination(int tn, int tk)
{
ll ret = 1;
for(int i=tn,j=1;j<=tk;j++,i--)
{
ret = ret*i/j;
if(ret>N) return ret; // 防爆
}
return ret;
}
bool check(int k) // Cnk
{
ll l = 2*k, r = max(l,N);
ll x;
while(l<r)
{
ll mid = (l+r)/2;
x = combination(mid,k);
if(x>=N) r = mid;
else l = mid + 1;
}
if(combination(r,k)!=N) return false;
n = k;
cout << r*(r+1)/2+k+1 << endl;
return true;
}
int main()
{
cin >> N;
for(int i=16;;i--)
if(check(i)) break;
return 0;
}
分析:
纯思维题,找到规律斜着枚举,最多技巧是二分。就Cnk组合数,劈成两半只看左边,斜着看每一列是递增的,横着往右是递增,所以导致某一个是N那么它左边和斜着上去绝对是小的,所以从里面往外枚举。
没做出来的原因:
万万想不到系列TAT+y总nb