CF1301C-Ayoub's function 组合数学 思维

这道题觉得很巧妙。

让含1的子串尽可能多,就是全为0的子串尽可能少。(注意是全为0,不是有0,开始这里想当然然后就卡住了=.=)。

总的子串数就是(1,1)(1,2)...(1,n)(2,2)..(2,n)..(n,n),显然是(n+1) * n/2。

我们考虑全为0的串数。我们有m个1,相当于有m+1的空隙可以用来放0。那么显然我们把这n-m个0匀着放到这m+1个空隙,可以使得每个0的部分尽可能短,进而使得全为0的子串尽可能少。

所以每个空隙放b=(n-m)/(m+1)。因为不能整除,所有有(n-m) % (m+1)个空隙实际上还要再多一个0。

如果每个空隙都放a = (n-m)/(m+1)个,那么显然每个空隙产生  a * (a + 1) / 2,一共产生(m + 1) * a * (a + 1) / 2 个全为0的子串。但是有b个空隙实际上还有一个0,所以还要在多产生b * (a+1)个串。

 1 #include <cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 int n,m,T;
 5 int main()
 6 {
 7     for (scanf("%d",&T);T;T--)
 8     {
 9         scanf("%d%d",&n,&m);
10         ll tot = (ll)n * (n + 1) / 2;
11         ll a = (n - m) / (m + 1);
12         ll b = (n - m) % (m + 1); 
13         printf("%I64d
",tot - a * (a + 1) / 2 * (m +  1) - (a + 1) * b);
14     }
15     return 0;
16 }
原文地址:https://www.cnblogs.com/iat14/p/12315682.html