gym102452J Junior Mathematician 2019ICPC 香港

https://codeforces.com/gym/102452/problem/J

My teammate gave me a "isn’t this basic operation?" f(x)=(\sum{d(x,i)} ^2-\sum{(d(x,i))^2}) /2, so the things to be maintained are converted to only related to the current coordinates, and then since a sum square and each number need to be calculated separately, and there is a /2 behind, then m=2m, and then 120 space I can’t open it, and the time is not good enough. I fall into a long autism.

Then I found that as long as the prefix sum and the remaining two dimensions are maintained, without this /2, the space of 60 can be stuck, and the time has been optimized by 4 times, and it is much simpler

dp[k][x][y] is the case where the prefix sum to the k-th position is x, y is the difference between x and f(x) before i is %m

Then suppose the number i is currently selected, then the transfer is dp[k][x][y]->dp[i][x+i][y+x*ii*mi[len-i]], because the new entry 1 Bit f(x) adds prefix and *i

In the end, there is only one solution when y==0

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int maxl=5e3+10;
const int mod=1e9+7;
 
int llen,rlen,m,len,mt;
ll ans;
int a[maxl];
ll dp[maxl][61][61][2];
int clk[maxl][61][61][2];
int mi[maxl];
char l[maxl],r[maxl];
 
inline void prework()
{
  scanf("%s",l+1);
  llen=strlen(l+1);
  scanf("%s",r+1);
  rlen=strlen(r+1);
  scanf("%d",&m);
}
 
inline void add(ll &x,ll y)
{
  x=(x+y)%mod;
}
 
inline int mo(int x)
{
  return (x%m+m)%m;
}
 
inline ll dfs(int k,int x,int y,bool f)
{
  if(k>len)
    return y==0;
  if(clk[k][x][y][f]==mt)
    return dp[k][x][y][f];
  int up=f?a[k]:9;
  dp[k][x][y][f]=0;
  for(int i=0;i<=up;i++)
    add(dp[k][x][y][f],dfs(k+1,(x+i)%m,mo(y+x*i-mi[len-k]*i),f && (i==up)));
  clk[k][x][y][f]=mt;
  return dp[k][x][y][f];
}
 
inline void mainwork()
{
  len=rlen;mi[0]=1;++mt;
  for(int i=1;i<=len;i++)
    a[i]=r[i]-'0',mi[i]=mi[i-1]*10%m;
  ll tmp1=dfs(1,0,0,1);
  
  len=llen;++mt;
  for(int i=1;i<=len;i++)
    a[i]=l[i]-'0';  
  ll tmp2=dfs(1,0,0,1);  
  
  int x=0;
  for(int i=1;i<=llen;i++)
    x=(x+mi[llen-i]*a[i])%m;
  int fx=0;
  for(int i=1;i<llen;i++)
    for(int j=i+1;j<=llen;j++)
      fx=(fx+a[i]*a[j])%m;
  if(fx==x)
    ans=((tmp1-tmp2+1)%mod+mod)%mod;
  else
    ans=((tmp1-tmp2)%mod+mod)%mod;
}
 
inline void print()
{
  printf("%lld\n",ans);
}
 
int main()
{
  int t;
  scanf("%d",&t);
  for(int i=1;i<=t;i++)
    {
      prework();
      mainwork();
      print();
    }
  return 0;
}

 

 

Guess you like

Origin blog.csdn.net/liufengwei1/article/details/108437142