一道我想骂人的题,差点把我气炸了。
题意:
求一个数的集合中(非多重集,每个数只出现一次)所有子集的gcd的和。结果MOD10^8+7输出。
输入输出不说了,自己看吧,不想写了。
当时我真把它当作数论题来写了,以为可以推导出什么公式然后化简大量重复的操作的。结果最后也没找到。最后题解说是dp,我同学说是暴力,吐血10升。
然后弄出来dp方程之后还是反复的wa,方程明明没啥问题,愣是卡了2个小时找不出错误,心情烦躁的要命,坑爹的室友还各种看视频打游戏,还不带耳机,我自己只好带着耳机大声放音乐,最后连音乐都听不下去了,恶心的想吐。
后来实在无奈了查了下题解,但是没人用dp写,有个用莫比乌斯反演的orz,还有个用暴力的,不过其实有dp的思想在里面。当然这不重要,重要的是我看见了他MOD加的位置挺有意思的,然后猛然想到我的int爆了!因为需要一个小于10^8的数×一个小于1000的数,这个数有可能爆!我叉!特么这不是故意卡int的意思吗?最后把这个改了终于过了……此时距离比赛结束已经5个小时了,我*!
状态转移方程:
dp[i][a[i]] += 1;
dp[i][j] += dp[i-1][j];
dp[i][gcd[j][a[i]]] += dp[i-1][j];
其中gcd[][]是预处理离线出来的,要不然可能会超时。
状态dp[i][j]表示在前n个数的集合中,gcd为j的集合有多少个。
方程表示三种情况:
- 只有a[i]的集合。
- 不存在a[i],只存在前i-1个数中若干数的集合。
- 存在a[i],且存在前i-1个数中若干数的集合。
时间复杂度为O(n*maxn),其中maxn为a[]数组中的最大值。
具体见代码——
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 #define LL long long 7 8 const int N = 1010; 9 const int Mod = 100000007; 10 11 int a[N]; 12 LL dp[N][N]; 13 int gcd[N][N]; 14 int t, n; 15 16 int Gcd(int x, int y) 17 { 18 if(x < y) 19 { 20 int t = x; 21 x = y; 22 y = t; 23 } 24 while(y != 0) 25 { 26 int t = y; 27 y = x%y; 28 x = t; 29 } 30 return x; 31 } 32 33 void Table() 34 { 35 for(int i = 1; i < 1005; i++) 36 { 37 for(int j = 1; j <= i; j++) 38 { 39 gcd[i][j] = gcd[j][i] = Gcd(i, j); 40 } 41 } 42 } 43 44 int main() 45 { 46 //freopen("test.in", "r", stdin); 47 Table(); 48 scanf("%d", &t); 49 for(int tm = 1; tm <= t; tm++) 50 { 51 scanf("%d", &n); 52 int maxn = 0; 53 for(int i = 0; i < n; i++) 54 { 55 scanf("%d", &a[i]); 56 maxn = maxn > a[i] ? maxn : a[i]; 57 } 58 memset(dp, 0, sizeof(dp)); 59 dp[0][a[0]] = 1; 60 for(int i = 1; i < n; i++) 61 { 62 dp[i][a[i]] += 1; //转移方程1 63 for(int j = 1; j <= maxn; j++) 64 { 65 dp[i][j] += dp[i-1][j]; //转移方程2 66 dp[i][gcd[j][a[i]]] += dp[i-1][j]; //转移方程3 67 dp[i][j] %= Mod; 68 dp[i][gcd[j][a[i]]] %= Mod; 69 } 70 } 71 int ans = 0; 72 for(int i = 1; i <= maxn; i++) 73 { 74 ans += (dp[n-1][i]*i)%Mod; //这里小心dp如果是int可能会爆 75 ans %= Mod; 76 } 77 78 printf("%d\n", ans); 79 } 80 return 0; 81 }
自己确实挺弱的,还需要努力,但是今天确实非常烦!所有认为这些没什么好烦的,都是因为他没有身临其境的感觉。
时间: 2024-10-15 06:53:36