2015ACM-ICPC 北京赛区 Problem K. A Math Problem

Description 
 Stan is crazy about math. One day, he was confronted with an interesting integer function defined on positive integers, which satisfies f(1) = 1 and for every positive integer n, 3× f(n) × f(2n+1) = f(2n) × (1 + 3f(n)), f(2n) < 6×f(n).  He wanted to know, in the range of 1 to n, for a given k, what are f(i) mod k like. For simplicity, you could just calculate the number of i which satisfies f(i) mod k = t for every t in range of 0 to k – 1 as g(t), and tell Stan what is all g(x) xor up is. 
Input 
 There are no more than 40 test cases.  The first line of the input contains an integer T which means the number of test cases.  Each test case contains two integer, n, k, just as mentioned earlier. Please note that n ≤ 1018, and k is a known Fermat prime -- that is to say, k is among { 3,5,17,257,65537} .  
Output 
 
For each test case, output the result of all g(x) xor up. 
Sample Input 
2 1 3 5 5 
Sample Output 

1 3 


题目大意:

有个函数满足

3× f(n) × f(2n+1) = f(2n) × (1 + 3f(n)), f(2n) < 6×f(n)

且f(2n)<6*f(n)

输入n和k

另g(x)为f(n)%k==x的个数

x为0到k-1之间

求g(x)的异或和



因为有个小于号限定

所以f(2n)=3*f(n)

f(2n+1)=3*f(n)+1

然后我们可以迭代

设fx(n)为处理函数

对于n为偶数

则处理fx(n/2),然后将其中的余数*3和*3+1求出fx(n)

若n为奇数

则迭代fx(n-1)再暴力求出f(n)即可

P,S 因为没找到评测的地方所以正确性不保证

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

update:在hiho上交了。过了

<pre name="code" class="cpp">#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int k;
long long sx[65537],tsx[65537];
inline int cale(long long n)
{
	if(n==1)
		return 1;
	else if(n%2==1)
		return (3*cale((n-1)/2)+1)%k;
	else
		return 3*cale(n/2)%k;
}
inline void fx(long long n)
{
	if(n==1)
	{
		sx[1]=1;
		return ;
	}
	int i;
	if(n%2==0)
	{
		fx(n/2);
		memset(tsx,0,sizeof(tsx));
		for(i=0;i<=k-1;i++)
		{
			tsx[i*3%k]+=sx[i];
			tsx[(i*3+1)%k]+=sx[i];
		}
		for(i=0;i<=k-1;i++)
			sx[i]=tsx[i];
		sx[1]++;
		sx[cale(n+1)]--;
	}
	else
	{
		fx(n-1);
		sx[cale(n)]++;
	}
}
int main()
{
	freopen("k.in","r",stdin);
	freopen("k.out","w",stdout);
	int T;
	scanf("%d",&T);
	while(T>0)
	{
		T--;
		int i;
		long long n;
		scanf("%lld%d",&n,&k);
		memset(sx,0,sizeof(sx));
		fx(n); 
		long long ans=0;
		for(i=0;i<=k-1;i++)
			ans=(ans^sx[i]);
	//	for(i=0;i<=k-1;i++)
	//		printf("%lld ",sx[i]);
	//	printf("\n");
		printf("%lld\n",ans);
	}
	return 0;
}



                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值