2015北京现场赛 Hihocoder 1259 :A Math Problem

来源:互联网 发布:淘宝物流单号查询 编辑:程序博客网 时间:2024/05/16 09:29
K - A Math Problem
Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu
Submit Status Practice UVALive 7271

Description

Download as PDF

题意:已知f(1)=1,还有f(n)的一堆关系,定义g(t)为f(i)%k==t 的个数。求g(0)^g(1)....^g(k-1)。

思路;先化简公式可以得到,f(2n)=3f(n),f(2n+1)=3f(n)+1,很明显就要把一个数化成二进制,然后每一位的权值=3^(位数-1),然后就用数位dp统计就好了。代码如下:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<utility>#include<map>#define maxn 65540#define inf 0x3f3f3f3ftypedef long long LL;using namespace std;const int mod = 1e9 + 7;int num[70], k, vis[maxn];LL temp[maxn], dp[70][maxn], three[70];void dfs(int pos, int status,  int limit){if (pos < 1){temp[status]++;return;}if (!limit&&vis[pos]){int now = status*three[pos + 1] % k;for (int i = 0; i < k; i++){temp[(now + i) % k] += dp[pos][i];}return;}int end = limit ? num[pos] : 1;for (int i = 0; i <= end; i++)dfs(pos - 1, (status * 3 + i) % k,  limit&&i == end);if (!limit){vis[pos] = 1;for (int i = 0; i < k; i++){dp[pos][i] = temp[i]; }}}void solve(LL x){int len = 0;while (x){num[++len] = x & 1;x >>= 1;}dfs(len, 0, 1);}int main(){three[1] = 1;int t;scanf("%d", &t);while (t--){memset(temp, 0, sizeof(temp));memset(dp, -1, sizeof(dp));memset(vis, 0, sizeof(vis));LL n;scanf("%lld%d", &n, &k);for (int i = 2; i < 70; i++){three[i] = three[i - 1] * 3 % k;}solve(n);temp[0]--;LL ans = 0;for (int i = 0; i<k; i++){ans ^= temp[i];}printf("%lld\n", ans);}}


0 0