QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#742748 | #9619. 乘积,欧拉函数,求和 | Aicu123 | TL | 72ms | 4376kb | C++20 | 4.4kb | 2024-11-13 17:13:55 | 2024-11-13 17:13:56 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define pii pair<int,int>
#define fi first
#define se second
//cout<<setiosflags(ios::fixed)<<setprecision(K);
const int dx[4]={1,-1,0,0};
const int dy[4]={0,0,1,-1};
const double eps=1e-9;
const double PI=acos(-1.0);
const int inf=1e9+7;
const int mod=998244353;
const int m=16;
const int prime[m]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
// assume -P <= x < 2P
const int P=mod;
int norm(int x) {
if (x < 0) x += P;
if (x >= P) x -= P;
return x;
}
template<class T>
T power(T a, ll b) {
T res = 1;
for (; b; b /= 2, a *= a) {
if (b % 2) {res *= a;}
}
return res;
}
struct Z {
int x;
Z(int x = 0) : x(norm(x)) {}
Z(ll x) : x(norm(x % P)) {}
int val() const {
return x;
}
Z operator-() const {
return Z(norm(P - x));
}
Z inv() const {
assert(x != 0);
return power(*this, P - 2);
}
Z &operator*=(const Z &rhs) {
x = (ll)x * rhs.x % P;
return *this;
}
Z &operator+=(const Z &rhs) {
x = norm(x + rhs.x);
return *this;
}
Z &operator-=(const Z &rhs) {
x = norm(x - rhs.x);
return *this;
}
Z &operator/=(const Z &rhs) {
return *this *= rhs.inv();
}
friend Z operator*(const Z &lhs, const Z &rhs) {
Z res = lhs;res *= rhs;
return res;
}
friend Z operator+(const Z &lhs, const Z &rhs) {
Z res = lhs;res += rhs;
return res;
}
friend Z operator-(const Z &lhs, const Z &rhs) {
Z res = lhs;res -= rhs;
return res;
}
friend Z operator/(const Z &lhs, const Z &rhs) {
Z res = lhs;res /= rhs;
return res;
}
friend std::istream &operator>>(std::istream &is, Z &a) {
int v;is >> v;
a = Z(v);
return is;
}
friend std::ostream &operator<<(std::ostream &os, const Z &a) {
return os << a.val();
}
};
void solve(){
int n;cin>>n;
vector<int>a(n+1);
for(int i=1;i<=n;i++) cin>>a[i];
vector<int>v(n+1);
vector<int>b(n+1,-1);
auto decompose=[&](int x,int idx) -> void {
for(int i=0;i<m;i++){
int j=prime[i];
while(x%j==0) v[idx]|=1<<i,x/=j;
}
if(x!=1) b[idx]=x;
};
for(int i=1;i<=n;i++){
decompose(a[i],i);
}
vector<int>p(n+1);
iota(p.begin()+1,p.end(),1);
sort(p.begin()+1,p.end(),[&](int x,int y){
return b[x]<b[y];
});
vector<Z>d(1<<m,1);
for(int i=0;i<1<<m;i++){
for(int j=0;j<m;j++){
if(i>>j&1){
d[i]*=(prime[j]-1);
d[i]/=prime[j];
}
}
}
int L=1;
// i 是prime是否出现的状压,j 是大质数是否出现过
vector<array<Z,2>>f(1<<m),g(1<<m);
f[0][0]=1;
while(L<=n){
int R=L+1;
while(R<=n&&b[p[R]]==b[p[L]]) R++;
for(int i=L;i<R;i++){
int j=p[i];
//不用a[j]
g=f;
//使用a[j]
//转移 k->nx
for(int k=0;k<1<<m;k++){
int nx=k|v[j];
int y=k&v[j];
//新加的质数
int t=v[j]-y;
//要乘上的数
Z mul=a[j];
mul*=d[t];
// for(int u=0;u<m;u++){
// if(t>>u&1){
// mul=mul/prime[u]*(prime[u]-1);
// }
// }
//是否是第一次加上这个最大质数
if(b[j]!=-1){
g[nx][1]+=f[k][0]*(mul/b[j]*(b[j]-1));
g[nx][1]+=f[k][1]*mul;
} else {
g[nx][0]+=f[k][0]*mul;
}
}
f=g;
}
//转移到下一个状态
for(int k=0;k<1<<m;k++){
g[k][0]=g[k][1]=0;
g[k][0]=f[k][1]+f[k][0];
}
f=g;
L=R;
}
Z ans=0;
for(int k=0;k<1<<m;k++){
ans+=f[k][0];
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
//cin>>T;
while(T--){
solve();
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 72ms
memory: 4280kb
input:
5 1 6 8 6 2
output:
892
result:
ok single line: '892'
Test #2:
score: 0
Accepted
time: 72ms
memory: 4376kb
input:
5 3 8 3 7 8
output:
3157
result:
ok single line: '3157'
Test #3:
score: -100
Time Limit Exceeded
input:
2000 79 1 1 1 1 1 1 2803 1 1 1 1 1 1 1609 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2137 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 613 1 499 1 211 1 2927 1 1 1327 1 1 1123 1 907 1 2543 1 1 1 311 2683 1 1 1 1 2963 1 1 1 641 761 1 1 1 1 1 1 1 1 1 1 1 1489 2857 1 1 1 1 1 1 1 1 1 1 1 1 1 967 1 821 1 1 1 1 2143 1861...