Linking
C - Product
题意:
有
N
N
N 个盒子,每个盒子里有
L
i
Li
Li 个球,每个球上写有一个数
a
i
j
aij
aij。
现在要从每个盒子中都拿出一个球,问一共有多少种方案数使得拿出球上写的数乘积为
X
X
X?
思路:
思路1:
一共N层,对于每一层的每个数,都遍历上一层更新过后的结果,更新为新的结果,对应方案数也更新。
for(auto it : dp1)
{
int k=it.first, c=it.second;
if(x * k <= m) dp2[x*k]+=c;
}
思路2:
暴搜。
从上往下走,每一层遍历拿了哪个数,走到最后判断是否乘积是X。如果是,ans++。
可以剪枝判掉未到最后一层乘积已经大于X的情况。
但是一共N层,层数未知。一共1e5个物品。。
不明白为什么暴搜不会超时,还请清楚的大佬告知!
注意:
数比较大,所以要提前判断乘积之后不会超过X,不超过longlong范围。
要不然会莫名wa两个点。。
Code1:
const int N = 500010, mod = 1e9+7;
int T, n, m;
map<int,int> a[N];
int cnt[N];
int sum=1, ans;
signed main(){
Ios;
cin>>n>>m;
map<int,int> dp1, dp2;
for(int i=1;i<=n;i++)
{
int cnt;cin>>cnt;
for(int j=1;j<=cnt;j++)
{
int x;cin>>x;
if(i==1) dp2[x]++;
for(auto it : dp1)
{
int k=it.first, c=it.second;
if(x * k <= m) dp2[x*k]+=c;
}
}
dp1 = dp2;
dp2.clear();
}
cout<<dp1[m];
Code2:
const int N = 500010, mod = 1e9+7;
int T, n, m;
map<int,int> a[N];
int cnt[N];
int sum=1, ans;
void dfs(int u)
{
if(u==n+1)
{
if(sum==m) ans++;
return;
}
for(int i=1;i<=cnt[u];i++)
{
// if(((m / sum) % a[u][i]) != 0) continue;
if(sum*a[u][i]>m) continue;
sum *= a[u][i];
if(sum <= m && m%sum==0) dfs(u+1);
sum /= a[u][i];
}
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin >> cnt[i];
for(int j=1;j<=cnt[i];j++)
{
cin>>a[i][j];
}
}
dfs(1);
cout<<ans;
}
D - Count Interval
题意:
给出长度为 N 的数列,问一共有多少个连续子序列总和为 K?
思路:
前缀和板子题。
map存储当前位置的前缀和 si 出现的次数。
遍历每个位置,答案ans += mp[si - K]
,mp[si]++
。
Code:
map<int,int> mp;
const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];
signed main(){
cin>>n>>m;
mp[0]=1;
int sum=0,ans=0;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
sum+=x;
ans+=mp[sum-m];
mp[sum]++;
}
cout<<ans;
return 0;
}
E - Σ[k=0…10^100]floor(X/10 ^k)
题意:
就是给出一个长度不超过 5e5 的数字串,求其每次砍掉末位,所表示出的十进制数之和。
例如:输入:1225, 输出1360。(1225 + 122 + 12 + 1 = 1360)
思路:
这么大的数,肯定不能直接表示。于是很容易想到高精度。。 其实不用。
就像上面的例子,我们看到所有加数的个位上的数为1、2、2、5,所有加数的十位上的数为1、2、2,百位上的数为1、2…
不同位数上的数就是原数对应位置的前缀和。
所以直接模拟一遍加法就可以了。
Code:
const int N = 500010, mod = 1e9+7;
int T, n, m;
int a[N];
signed main(){
Ios;
string s;
getline(cin,s);
int len=s.size();
s=" "+s;
for(int i=1;i<=len;i++) a[i]=a[i-1]+s[i]-'0';
int t=0;
vector<int> v;
for(int i=len;i>=1;i--)
{
int x=t;
x += a[i];
v.push_back(x%10);
t = x/10;
}
if(t) cout<<t;
for(int i=v.size()-1;i>=0;i--) cout<<v[i];
return 0;
}
场上C题没判超范围的情况,卡住了。E题思维没转化过来。。
太菜了。。