欧拉函数。
欧拉函数打表模板:
#define maxn 3000010 int p[maxn]; void oula(){ int i,j; for(i=1; i<=maxn; i++) p[i]=i; for(i=2; i<=maxn; i+=2) p[i]/=2; for(i=3; i<=maxn; i+=2) if(p[i]==i) { for(j=i; j<=maxn; j+=i) p[j]=(p[j]/i*(i-1)); } }
题解:(说明:要不是看题解,自己真不敢这样写....,只能说数据有点弱。)
将欧拉函数打完表后,先将每个幸运数字排序一下。
然后枚举长度的同时,枚举每个幸运数字,如果当前长度对应的欧拉值大于等于幸运数字。直接就加上。
code1:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INF=1e9+7; const ll maxn=1e6+10; const ll N=1E6+20; ll p[N]; ll arr[N]; ll dp[N]; void oula(){ for(ll i=1;i<=maxn;i++) p[i]=i; for(ll i=2; i<=maxn; i+=2) p[i]/=2; for(ll i=3; i<=maxn; i+=2) if(p[i]==i){ for(ll j=i; j<=maxn; j+=i) p[j]=(p[j]/i*(i-1)); } } void solve(ll time){ ll n; cin>>n; ll ans=0; for(ll i=1;i<=n;i++) cin>>arr[i]; sort(arr+1,arr+1+n); for(int i=1,j=2;i<=n&&j<maxn;j++){ while(p[j]>=arr[i]&&i<=n) { ans+=j; i++; } } printf("Case %d: ",time); cout<<ans<<" Xukha "; } int main(){ oula(); ll t; cin>>t; for(ll i=1;i<=t;i++) solve(i); return 0; }
我的思路和code2差不多,但是我的一直调不对。。。
用一个数组dp,记录每个幸运数字对应的长度的最小值。
对一个长度i,其对应的欧拉值。枚举小于当前欧拉值并且还没有赋值的(可能没有对应长度,或者对应长度在后边)欧拉值赋值长度i。这样可以保证当前欧拉值为j,dp[j]可以表示,大于等于j的欧拉值所对应的最小长度。
秒~~
code2:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll maxn=1e6+10; const ll N=1E6+20; ll p[N]; ll arr[N]; ll dp[N]; void oula(){ for(ll i=1;i<=maxn;i++) p[i]=i; for(ll i=2; i<=maxn; i+=2) p[i]/=2; for(ll i=3; i<=maxn; i+=2) if(p[i]==i){ for(ll j=i; j<=maxn; j+=i) p[j]=(p[j]/i*(i-1)); } } void solve(ll time){ ll n; cin>>n; ll ans=0; for(ll i=1;i<=n;i++){ ll x; cin>>x; ans+=dp[x]; } printf("Case %d: %d Xukha ",time,ans); } int main(){ oula(); memset(dp,0,sizeof dp); for(ll i=1;i<=maxn;i++){ for(ll j=p[i];dp[j]==0&&j>=0;j--) dp[j]=i; } dp[1]=2; ll t; cin>>t; for(ll i=1;i<=t;i++) solve(i); return 0; }