先打表,找规律
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<long long>myset;
for(long long i=1;i<20;i++,cout<<endl)
{
myset.clear();
for(long long j=0;j<1000000;j++)
myset.insert(j*j%(1<<i));
cout<<i<<' '<<myset.size();
}
return 0;
}
f(i)=4*f(i-2)-5 通项 f(i)=(2^(n-1)+5)/3 i为奇数
f(i)=4*f(i-2)-4 f(i)=(2^(n-1)+4)/3 i为偶数
即 f(i)=(2^(n-1)+4+n%1)/3
若b%c=1,则a/b%c=a%c=d,证明如下:
b=c*k1+1 a=b*(c*k2+d)=(c*k1+1)*(c*k2+d)=c*(k1*k2+k1*d+k2)+d=c*k3+d
因此a%c=d=a/b%c
求解f(i)%mod,a/b%c=(a*k)/(b*k)%c=a*k%c,(b*k%c=1)
即求任一k使b*k%c=1, 即b*k=c*k'+1,设x=k,y=-k’,则x*b+y*c=1,extgcd或者打表求一个x即可
#include<iostream>
using namespace std;
int extgcd(int &x,int &y,int a,int b)
{
if(b==0){x=1,y=0;return a;}
int d=extgcd(x,y,b,a%b);
int t=x;x=y;y=t-a/b*y;
return d;
}
int main()
{
int x,y;
extgcd(x,y,3,10007);
cout<<x<<endl;
}
#include<iostream>
using namespace std;
int main()
{
for(int i=1;i<1000000;i++)
if(i*3%10007==1)
{
cout<<i<<endl;break;
}
}
所以f(i)=(2^(n-1)+4+n%1)*3336%10007.
#include<iostream>
using namespace std;
typedef long long ll;
const ll mod=10007;
ll pow(ll n)
{
ll ans=1,base=2;
while(n)
{
if(n&1) ans=ans*base%mod;
base=base*base%mod,n>>=1;
}
return ans;
}
int main()
{
ll t,n,cas=1;
cin>>t;
while(t--)
{
cin>>n;
cout<<"Case #"<<cas++<<": "<<3336*(pow(n-1)+4+(n&1))%mod<<endl;
}
return 0;
}