挣扎过程:
刚开始在想是怎么变化,从左到右变化,或者从后到下变化,会不会影响结果,于是打表,发现这样真的会不一样,企图通过打表来看出数学规律。但是后面发现宏观来看,就是如果这个阶段有n行,如果该行为第a行,若a<n/2,那么改行红球数等于上一阶段的红球数,否则,等于上一阶段的改行红球数。
也就是说这是计算一行行的红球数,但是行数是1-2的30次方,tle了。
紫书思路是从段的角度,要求第a行到第b行,那么就是求前b行的红球数减去前a行的红球数,而由于行有规律,段也是有规律的,如果在在前半段,那么改行以上的红球数等于上一阶段该行以上的红球数*2,否则等于改行以上的红球数加上3的k-1次方(k表示阶段)。
#include<cstdio>
#include<iostream>
#define ll long long int
using namespace std;
ll cube(int a,int b)
{
ll sum=1;
for(int i=1;i<=b;i++)sum*=a;
return sum;
}
ll solve(int k,ll a,ll c2,ll c3 )
{
if(k==0)if(a%2)return 1;else return 0;
if(a>c2)return solve(k-1,a-c2,c2/2,c3/3)+c3*2;
else return solve(k-1,a,c2/2,c3/3)*2;
}
int main(void)
{
int cas;
scanf("%d",&cas);
for(int ca=1;ca<=cas;ca++)
{
int k;
ll a,b;
cin>>k>>a>>b;
ll ans=0;
ans-=solve(k,a-1,cube(2,k-1),cube(3,k-1));
ans+=solve(k,b,cube(2,k-1),cube(3,k-1));
printf("Case %d: %lld\n",ca,ans);
}
}